5 ms·
Carrot Disclosure: Forgejo
- dangus 5mo agoThe author's attitude is so off-putting. What gives? Did Forgejo hurt you? The Forgejo disclosure process looked pretty simple and straightforward to me. The bold and all-caps words that bothered the author are just making sure you know how to disclose vulnerabilities safely without leaking zero-day exploits to a wider audience than necessary. I'm also not impressed with a carrot disclosure that looks like this. Running a python script to compromise a locally hosted instance? Bruh, you have physical hardware and host shell access. That python script could be doing anything including running as root. Show us the exploit hitting a remote server.
- shimman 5mo agoSeriously, this author comes across as an absolute sore loser if this is the PR they are referring too: https://codeberg.org/forgejo/forgejo/pulls/12283 https://codeberg.org/forgejo/forgejo/pulls/12283 Someone asking you to write a test for new code and then making this blog in response is just so pathetic.
- onedognight 5mo agoTo hell with writing a test for you. That’s what you say to someone who gets paid by you. If the project doesn’t want the fix. That’s their issue, not the reporter’s.
- akoboldfrying 5mo agoLook at the big picture. The maintainers likely deal with many low-quality bug reports and PRs coming in, especially from AI, and the incentive to spam these is not going away anytime soon. How should they best allocate their limited attention? One way is for the PR maker to signal their own attention to detail/effort/commitment by jumping through the (quite reasonable) hoop of writing a test. Is this extra effort? Yes. But if your motivation in opening the PR in the first place is genuinely to improve the world, then do the slightly harder thing that actually improves the world given the constraints on maintainer attention it operates under, not the thing that is slightly easier for you but leaves your contribution indistinguishable from the sea of slop out there.
- martey 5mo agoWhile I agree with you that this blog post (and the "carrot disclosure" described in it) is ill-considered, the pull request is not really "new code", it adds quotes to HTML attributes that are missing them. I think it's entirely reasonable for a contributor to assume that a new test case would not be needed for this small change, and that the maintainer's response ("So a simple question: is this code covered under a test? If not, you will have to add one.") is more abrasive than necessary.
- preisschild 5mo agoa test is probably not the right thing for this, but adding a linting rule so that quoting is enforced everywhere is probably the right way to go
- Chris2048 5mo ago> Someone asking you to write a test for new code per the response: "I'm not sure what kind of test would you like me to write for this change, as it's simply adding 4 quotes"
- shimman 5mo agoThat totally justifies the very normal extortion like blog post in response.
- kstrauser 5mo agoMaybe one showing that the change doesn't make it worse. Here's the code change: - <a class="item muted sidebar-item-link" href=${$(this).data('href')}> + <a class="item muted sidebar-item-link" href="${$(this).data('href')}"> I know zero about this code path, but suppose it's expected that `${$(this).data('href')}` is already a properly quoted value, like `"https://example.com https://example.com"`. Then the first line expands to: <a class="item muted sidebar-item-link" href="https://example.com"> and the second expands to: <a class="item muted sidebar-item-link" href=""https://example.com""> which would have all kinds of room for mischief. Or suppose the template engine auto-quotes values that it injects, so the quotes aren't necessary at all, which is a pretty common approach. The point is that you don't randomly want to throw quotes into HTML or single quotes into SQL just for giggles. You have to write tests demonstrating that the existing common use cases still work after the change, even if it's simply adding 4 quotes.
- MajesticHobo2 5mo agoI'd say also add a test that shows the HTML injection (which spurred the PR) isn't possible. Given an attacker-controlled URL of: foo onclick the following shouldn't render: <a class="item muted sidebar-item-link" href=foo onclick> The following should: <a class="item muted sidebar-item-link" href="foo onclick">
- kstrauser 5mo agoOh, for sure! That'd end the conversation: "your change breaks the existing tests. Fix that and we'll re-consider."
- quectophoton 5mo ago> I'm also not impressed with a carrot disclosure that looks like this. Running a python script to compromise a locally hosted instance? Bruh, you have physical hardware and host shell access. That python script could be doing anything including running as root. > Show us the exploit hitting a remote server. Watch out, their script works on HN too, as a proof here's me logging in to YOUR computer's root account (a bit more redacted for obvious reasons): $ python3 ./poc/chain_alpha.py --target dangus > out.txt $ grep Backdoor out.txt | sed -r 's@[^:]+$@ [REDACTED]@g' [+] Backdoor admin created: [REDACTED] $ grep IP out.txt | sed -r 's@[^:]+$@ [REDACTED]@g' [+] IPv4 address for dangus: [REDACTED] $ grep 'debug2: shell' out.txt [+] debug2: shell request accepted on channel 0 $ tail -n12 out.txt ================================================================ [+] COMMAND EXECUTION CONFIRMED! ================================================================ Server-side output (received via SSH, with `set -x`): + id -u 0 + id -g 0 ================================================================ $ sha256 ./poc/chain_alpha.py c10d28a5ff74646683953874b035ca6ba56742db2f95198b54e561523e1880d7 ./poc/chain_alpha.py
- unethical_ban 5mo agoFrom a linked PR (related to this RCE?), from a maintainer who closed it: >Just thinking something not being used is not enough, even if it's a security sensitive topic Linux kernel seems to disagree. This is a dangerously naive way to think of networked software in the AI age. --- edit: I got hit with the "posting too fast" block again, so I'll reply to dangus here: >While a remote host would further prove the claim, the person clearly claims it is RCE, not just CE. It would be quite the pie in the face if the author wrote a python script to take in an IP address but modified system files on the backend to create a stunt.
- dangus 5mo agoIt would definitely be a bit silly for the author to make a fake carrot disclosure, but I thought of it just because of how reading this article made me feel distrust toward the author. IDK, they just seem like kind of a jerk! Now, I don't think the PRs with the Forgejo folks show a lot of warm collaborative energy on their side, either, but I can see how soft skills from the author would likely have taken their PRs a lot further in getting what they want. But the author's whole attitude is that Forejo is such a mess and it's barely worth their time to try and clean it up. Nobody's twisting their arm to contribute to an open source project that they don't even like! From the perspective of Forgejo maintainers, the author is just some random new contributor barging in and telling them to drop some legacy support that hasn't been discussed in detail yet. And of course, this new contributor hasn't actually followed the security policy to disclose it as a high severity issue to justify the change.
- chillfox 5mo agoDon’t forget, repeatedly ignoring the requirements for including tests, and instead offering up a “have tested it locally, trust me” as a substitute.
- conartist6 5mo agoThe worry here is that they need to leave the security hole open because they're using it?
- 000ooo000 5mo agoHopefully someone a little more.. pragmatic gets eyes on that linked PR.
- preinheimer 5mo agoThere’s an old cryptography story. A cryptographer friend tells the story of an amateur who kept bothering him with the cipher he invented. The cryptographer would break the cipher, the amateur would make a change to “fix” it, and the cryptographer would break it again. This exchange went on a few times until the cryptographer became fed up. When the amateur visited him to hear what the cryptographer thought, the cryptographer put three envelopes face down on the table. “In each of these envelopes is an attack against your cipher. Take one and read it. Don’t come back until you’ve discovered the other two attacks.” The amateur was never heard from again. https://www.schneier.com/crypto-gram/archives/1998/1015.html https://www.schneier.com/crypto-gram/archives/1998/1015.html
- neilv 5mo agoAnd if you are a dishonest cryptographer, you only need to find one attack to pull this off.
- reverius42 5mo agoAnd who in the OP's post is the cryptographer, and who's the amateur, in this allegory?
- preinheimer 5mo agoI think the OP is presenting themselves as the cryptographer, and the authors behind Forgejo as the amateur. At this point they've only filled one envelope but believe there is many more to find, and are hoping that in the process of tracking down this one they'll find more.
- mmsc 5mo agohttps://codeberg.org/forgejo/governance/src/commit/5c07b3801537212ed6be1edfec298d7b004ce92d/SECURITY-POLICY.md https://codeberg.org/forgejo/governance/src/commit/5c07b3801... > Failure to comply with these rules will be criticized publicly, and we reserve the right to no longer coordinate with you or your project in the future. lol
- stock_toaster 5mo agoI could totally imagine this kind of thing being added due to AI-slop security report overload, like curl was experiencing[1]. [1]: https://daniel.haxx.se/blog/2025/07/14/death-by-a-thousand-slops/ https://daniel.haxx.se/blog/2025/07/14/death-by-a-thousand-s...
- jorams 5mo agoThis is a weird post to be honest. You've found a whole bunch of serious security issues, filed two PRs, one of which is adding some quotes because > Those aren't exploitable XSS, but it doesn't hurt to have a second layer of defense. The other suggests breaking clients that aren't using the more secure version of an OAuth method because > I can't think of any OAuth client that would like to [use it] That second one is a good idea, but the maintainer is also right to ask for some discussion before introducing a breaking change. But crucially: neither of these are the kind of significant security issues you've found. Maybe lead with an actual bug?
- arcfour 5mo agoClosing the PR without providing feedback beyond "needs further discussion" does not engender said further discussion.
- PunchyHamster 5mo agoPR isn't a place for discussion about what or how to implement change in the first place, that should be forum/mailing list/issues and there is open issue for that discussion https://codeberg.org/forgejo/forgejo/issues/8634 https://codeberg.org/forgejo/forgejo/issues/8634
- radlad 5mo ago#8634 is specifically about a breaking change that occurred in v12. It's literally the first line of what you linked: > In the v12 release of Forgejo (fixed in v12.0.1) there have been breaking changes that impact third-party authentication sources that use Forgejo as a provider. If you have been affected, please help us assessing the impact ...
- henryteeare 5mo agoThe response was, "needs a discussion," as in a post on `https://codeberg.org/forgejo/discussions https://codeberg.org/forgejo/discussions`, rather than directly creating a PR. There also was feedback saying approximately that they've been burned by security changes in the recent past and don't want to run into similar issues without due consideration.
- gchamonlive 5mo agoIn the age of AI, carrot disclosure is potentially a full disclosure with extra steps. I'm no security expert, but with the context provided, the forgejo codebase and the outline of the redacted script, I think there is a good chance I could use codex to crunch through the vuln chain and reproduce the script.
- nine_k 5mo agoWhere's the vuln chain? Is it even obvious which APIs have been called?
- gchamonlive 5mo ago--- In this session we are going to explore the vulnerabilities documented in this carrot disclosure post at https://dustri.org/b/carrot-disclosure-forgejo.html https://dustri.org/b/carrot-disclosure-forgejo.html and try to reproduce the script that explores the chain to gain admin access to forgego. The post mentions just briefly what's been used to create the vuln chain: `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 some of them to obtain a full-blown RCE`. There is also the outline of the script call and the output we will use to base the script reproduction: ``` $ python3 ./chain_alpha.py --target http://127.0.0.1:3000 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 ./poc/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 $ ``` Our working directory already contains the source for forgego. I am no security expert so we will need to approach this in four stages: First I need you to guide me through each of the vuln concepts exposed in the article. In this step I am going to read through them and understand each of them. I am also not familiar with forgego codebase, so in the second step I need you to guide me through the code, as we explore and understand the architecture and implementation of this git platform. In the third stage we are going to validate my understanding of the first stage by linking each of the concept with the actual codebase. Finally, in the fourth stage we are most likely prepared to tackle reproducing the vuln chain exploit. Create one work item for each step. We are going to go through each of them in separate sessions.
- flumpcakes 5mo agoDid the author actually disclose this RCE or just open random PRs and claim there's an issue? It doesn't appear like the author is acting in good faith, instead grandstanding in public because they feel superior.
- apublicfrog 5mo agoThe author quite clearly outlines their reasoning for this in the article: > 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. Users of this disclosure model are of course called Bugs Bunnies.
- flumpcakes 5mo agoSeems like grandstanding bad faith to me. They didn't even bother to follow the established disclosure policy for this project because the author feels this quality of the code is so crap, so instead does this...
- apublicfrog 5mo agoMaybe, but I can see why people don't want to deal with red tape to do someone a favour. Once I tried to help an open source project with a bug and was rejected because I didn't agree to support the Ukraine, that all sexual orientations are equal, or whatever else the long winded contributor rules were. The issue isn't that I don't support those things, it's more that it's like someone handing me a 3 page form to fill out for picking their keys up for them. There also may be conventions on disclosure and exploits, but they're not based on the law or rules of society.
- isodev 5mo agoThis entire post reads as rage bait. They’re mad because Forgejo has … a process? And what are these vulnerabilities, concretely? > But given the sorry state of the codebase I honesty want a refund on the 10 minutes I wasted reading this.
- yunnpp 5mo agoI cracked at the last statement, lol. Really encapsulates my overall feeling reading some HN submissions lately.
- throwaway38294 5mo agoI run a forgejo instance at home but wouldn't dream of opening it up to the public. Works great, and fast on lan, but imo keep it there
- kasdklasmdads 5mo agoImagine if every open source contributor behaved like that. "I found performance problems in your software, but I won't disclose them until you fix them." "I'm a designer, but I won't disclose my improvement to your project until you adjust all the CSS bugs in your project." If that person is skilled with finding security bugs, then that could be their contribution to that open-source project, like any other contribution.
- gbraad 5mo agoThis is so wrong. Because he didn't like a PR removing a feature, and they haven't yet merged another PR that was opened yesterday?!?
- pabs3 5mo agoI note that the code that pull request 12283 is changing builds HTML via string concatenation/templates, which is a widespread source of XSS problems. Maybe it is time to for browsers and JavaScript runtimes/libraries to deprecate string based HTML building and require DOM based instead. The former is unsafe by design and the latter is a safe-by-construction approach. Getting HTML building right is a pretty basic building block of web apps, Forgejo can't have great security practices if they aren't doing that. So I can easily imagine the OP is correct in their assessment of Forgejo code security.
- jeremiahlee 5mo agoThe author sent 5 more pull requests fixing (tragically) fundamental security flaws. https://codeberg.org/forgejo/forgejo/pulls?q=&type=all&sort=relevance&state=open&labels=&milestone=0&project=0&assignee=0&poster=40118&archived=false https://codeberg.org/forgejo/forgejo/pulls?q=&type=all&sort=...
- bmitch3020 5mo agoForgejo has responded: > The author of the recent 'Carrot disclosure' blog post has contacted the Forgejo Security team with their findings. The issues raised concern defence-in-depth improvements and denial-of-service risks. There is no known RCE exploit possible without internal server credentials. > We believe these findings can be addressed publicly. The security team will open issues where approaches to implement new defensive measurements will be discussed, we believe there's no single answer and as such appreciate the opinion of other Forgejo contributors on this matter. https://floss.social/@forgejo/116494295922963052 https://floss.social/@forgejo/116494295922963052
- throwa356262 5mo agoOkay, this sounds familiar. If you run Claude Opus 4.6 at max settings on forgejo repo, it will give you a bunch of RCE's ... that need prior knowledge of the server internal token :) You have to tell the stupid LLM that these attacks doesn’t make sense. The author seem to be a experienced security researcher. I am surprised he didn't catch this.
- weiliddat 5mo agoLet's go one step further and think about why OSS maintainers generally approach security vulnerabilities the way they do (even pre-AI), and why some people has a significant negative reaction to this type of bug/security/issue reporting approach. What happens if they treat every single report with the same effort and seriousness regardless of how it is reported? What happens if they dedicate too much effort in wild goose hunts while disregarding the more mundane/concrete security and maintenance work? How would an attacker take advantage of this process? If you work in software, maybe you've encountered this yourself, in orgs where they don't have good processes around reporting bugs/issues. You essentially get DoSed by noise. You get tons of issues from customers (or internal stakeholders representing them), some barely describing stuff like "hey X can access Y, don't think they should" without any context (or even refusing to provide further information even after you ask), forcing you/CS to prune down all possible paths based on audit logs and their permission settings and so on. Customers (in this case I'd say OSS users are customers too) can say "yeah this is the responsibility of the maintainers/vendors, why should I even care to report things a certain way, be glad I even told you at all" but IME this social posture is terrible for both parties. Even in commercial relationships, the best customers I've had were ones that reported issues that were concrete and reproducible. The chances I can fix it almost immediately goes up in orders of magnitude. The customer gets what they want and my job is simpler. Even the core claim of the article, "this is a systemic issue", isn't fixed by a carrot disclosure. They don't imply an organizational/structural issue, merely a legacy one (inheriting stuff from gitea/gogs). What do you gain more by putting social-political pressure on an OSS project, if it's not a social-political problem? The post reads more like an emotional response (frustration) rather than a productive one.
- debee12322 5mo ago[flagged]