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, some information leaks, 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 some of
them to obtain a full-blown RCE, some secrets leaks, a bunch of persistent
account access, a handful of OAuth2 privesc, …
Fortunately (or unfortunately depending who you're asking), the RCE 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),
meaning that its 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 must or mustn't do should I decide
to go this way. But given the sorry state of the codebase (not their fault
though, they inherited the gitea/gogs ones), I'm pretty sure I
could spend another evening and find another chain, and odds are that others
have a bunch as well. I could try to fix the issues one by one myself and send
pull-requests, but even if
I
wanted, this is a
systemic issue, there is little point in playing endless wack-a-mole.
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.
So without further ado:
$ python3 ./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 ./chain_alpha.py
c10d28a5ff74646683953874b035ca6ba56742db2f95198b54e561523e1880d7 ./chain_alpha.py
jvoisin@chernabog 11:35 ~/Documents/exploits/forgejo tree
.
├── chain_alpha.py
├── chain_beta.py
├── chain_gamma.py
├── dos
│ ├── cpuburn_authenticated.py
│ ├── cpu_dos.py
│ ├── dbburn.py
│ ├── dfburn.py
│ ├── exhaust.py
│ ├── gburn.py
│ ├── grpstarve.py
│ ├── rstarve.py
│ ├── starve.py
│ └── storage.py
├── f9_repo_settings.py
├── get_version.py
├── leak_secrets.py
├── leak_token.py
├── merge.py
└── NOTES.md
2 directories, 19 files
$
[edit] you might be interested in the follow-up blogpost.
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Follow-up to Carrot disclosure: Forgejo | 0 | 7.3 | 30-04-2026 |
| 2 | The AI-authored Denial-of-Service attack | 0 | 8.9 | 07-07-2026 |
| 3 | Trivial anti-crawler with Caddy | 0 | 8.42 | 23-06-2026 |
| 4 | How Linux Security Teams Spot Vulnerabilities Before CVEs Are Published | 0 | 7 | 14-07-2026 |
| 5 | Drupal.org blog: Migrating issues from security.drupal.org to git.drupalcode.org | 5 | 7 | 17-07-2026 |
| 6 | When vendor-supplied support matters: How AI is changing the open source security equation | 0 | 15.95 | 28-07-2026 |
| 7 | Tag1 Insights: A New Direction for Authentication in Drupal Core | 0 | 5 | 15-07-2026 |
| 8 | FlashME! – WordPress vulnerability disclosure [CVE-2016-9263] | 0 | 9.77 | 19-10-2017 |
| 9 | EIP Editing Office Hour (EIP + ERC ) Meeting #108, July 28, 2026 | 0 | 18.32 | 27-07-2026 |
| 10 | Into the Borg – SSRF inside Google production network | 0 | 11.2 | 20-07-2018 |