Skip to content
HN On Hacker News ↗

Carrot disclosure: Forgejo

▲ 145 points 58 comments by bo0tzz 2mo ago HN discussion ↗

Pangram verdict · v3.3

We believe that this document is fully human-written

3 %

AI likelihood · overall

Human
100% human-written 0% AI-generated
SEGMENTS · HUMAN 3 of 3
SEGMENTS · AI 0 of 3
WORD COUNT 491
PEAK AI % 8% · §3
Analyzed
Apr 28
backend: pangram/v3.3
Segments scanned
3 windows
avg 164 words each
Distribution
100 / 0%
human / AI fraction
Verdict
Human
Pangram v3.3

Article text · 491 words · 3 segments analyzed

Human AI-generated
§1 Human · 1%

Since Fedora moved from Pagure to Forgejo, I finally had an incentive to take a good look at Forgejo's security posture. The results aren't pretty to be honest: SSRF in a lot of places, no CSP/Trusted-Types, a bit of ghetto templating in javascript, cryptographic malpractices, overlooks in the authentication mechanisms (OAuth2, OTP, sessions/access handling, post-compromission recovery, …), a bunch of low-hanging DoS, information leak all over the place, various TOCTOU, … All in all, it took me one evening after work to find a good amount of vulnerabilities (adding to the one I got from looking at gitea at some point in the past), and chain them to obtain a full-blown RCE, secrets leaks, persistent account access, OAuth2 privesc, …Fortunately (or unfortunately depending who you're asking), the exploit relies on open registration, and on a configuration option set to a non-default value (which is the case on some instances I've looked at, so nothing exotic). This means that the selling value is pretty low/nonexistent. I could disclose the bugs to Forgejo, they even have a Security Policy, with a lot of MUST/MUST NOT about what I should do do should I decide to go this way. But given the sorry state of the codebase, I'm pretty sure I could spend another evening and find another chain. I could spend time fixing the issues myself, but oh well.I discussed the conundrum with a friend of mine, and was told to put my money where my mouth is, and just go with carrot disclosure that I usually advocate for in this kind of situation: Carrot Disclosure, dangling a metaphorical carrot in front of the vendor to incentivise change. The main idea is to only publish the (redacted) output of the exploit for a critical vulnerability, to showcase that the software is exploitable. Now the vendor has two choices: either perform a holistic audit of its software, fixing as many issues as possible in the hope of fixing the showcased vulnerability; or losing users who might not be happy running a known-vulnerable software.

§2 Human · 5%

Users of this disclosure model are of course called Bugs Bunnies. So without further ado:$ python3 ./poc/chain_alpha.py --target http://127.0.0.1:3000 > out.txt $ grep Backdoor out.txt [+] Backdoor admin created: svc_ljeopgid / dukecepapsygiqks!A1 $ tail -n17 out.txt

================================================================ [+] COMMAND EXECUTION CONFIRMED! ================================================================

Server-side hook output (received via git push stderr):

remote: ========================================== remote: FORGEJO RCE PoC - Command Execution Proof remote: ========================================== remote: hostname: chernabog remote: uid: uid=1000(jvoisin) gid=1000(jvoisin) groups=1000(jvoisin),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 remote: date: Tue Apr 28 19:16:59 UTC 2026 remote: proof: chernabog remote: ==========================================

================================================================ $ sha256 ./poc/chain_alpha.py c10d28a5ff74646683953874b035ca6ba56742db2f95198b54e561523e1880d7 ./poc/chain_alpha.py $ ls -l ./poc total 140 -rw-r--r--. 1 jvoisin jvoisin 23530 Apr 28 21:18 chain_alpha.py -rw-r--r--. 1 jvoisin jvoisin 6382 Apr 28 01:14 chain_beta.py -rw-r--r--. 1 jvoisin jvoisin 11410 Apr 28 21:54 chain_gamma.py -rw-r--r--.

§3 Human · 8%

1 jvoisin jvoisin 10334 Apr 28 22:20 leak_secrets.py -rw-r--r--. 1 jvoisin jvoisin 9171 Apr 28 23:15 merge.py -rw-r--r--. 1 jvoisin jvoisin 83861 Apr 27 23:59 NOTES.md $