Given the large number of unmaintained or non-recent software out there, I think being worried is the right approach.
The only guaranteed winner is the LLM companies, who get to sell tokens to both sides.
Why? The attackers can run the defending software as well. As such they can test millions of testcases, and if one breaks through the defenses they can make it go live.
I'm quite optimistic about AI ultimately making systems more secure and well protected, shifting the overall balance towards the defenders.
https://projectzero.google/2024/10/from-naptime-to-big-sleep...
List of vulnerabilities found so far:
The defensive side needs everything to go right, all the time. The offensive side only needs something to go wrong once.
It's a subtle difference from what you said in that it's not like everything has to go right in a sequence for the defensive side, defenders just have to hope they committed enough into searching such that the offensive side has a significantly lowered chance of finding solutions they did not. Both the attackers and defenders are attacking a target program and sampling the same distribution for attacks, it's just that the defender is also iterating on patching any found exploits until their budget is exhausted.
It's probably more worrying as you get script kiddies on steroids which can spawn all around with same mindset as even the dumbest significant geopolitical actor out there.
There are countless bugs to fund.
If the offender runs these tools, then any bug they find becomes a cyberweapon.
If the defender runs these tools, they will not thwart the offender unless they find and fix all of the bugs.
Any vs all is not symmetric
For the calculus to change, anyone running an LLM to find bugs would have to be able to find all of the bugs that anyone else running an LLM could ever find.
That’s not going to happen.
A) 1 cyber security employee, 1 determined attacker
B) 100 cyber security employees, 100 determined attackers
Which is better for defender?
I don't think so. From a pure mathematical standpoint, you'd need better (or equal) results at avg@1 or maj@x, while the attacker needs just pass@x to succeed. That is, the red agent needs to work just once, while the blue agent needs to work all the time. Current agents are much better (20-30%) at pass@x than maj@x.
In real life that's why you sometimes see titles like "teenager hacks into multi-billion dollar company and installs crypto malware".
I do think that you're right in that we'll see improved security stance by using red v. blue agents "in a loop". But I also think that red has a mathematical advantage here.
> I don't think so. From a pure mathematical standpoint, you'd need better (or equal) results at avg@1 or maj@x, while the attacker needs just pass@x to succeed.
Executing remote code is a choice not some sort of force of nature.
Timesharing systems are inherently not safe and way too much effort is put into claiming the stone from Sisyphus.
SaaS and complex centralized software need to go and that is way over due.
If enough people cancel their leftpad-as-a-Service subscription the server can be unplugged.
(Yes I am somewhat hyperbolic and yes I see use for internet connected servers and clients. I argue against the SaaS driven centralization.)
How do we deal with the floods threatening those living in the valleys and slopes?
How does that help with the topic at hand? (LLM-assisted vulnerability research)
Are the decentralized systems that you prefer more secure/less buggy/less exploitable by LLMs?
Scary.
Yikes.
> Leak a libc Pointer via Use-After-Free. The exploit uses the vulnerability to leak a pointer to libc.
I doubt Rust would save you here unless the binary has very limited calls to libc, but would be much harder for a UaF to happen in Rust code.
Combine that with a minimal docker container and you don't even need a shell or anything but the kernel in those images.
AFAICT, static linking just means the set of vulnerabilities you get landed with won't change over time.
I use pure go implementations only, and that implies that there's no statically linked C ABI in my binaries. That's what disabling CGO means.
* It's likely that C implementations will have bugs related to dynamic memory allocation that are absent from the Go implementation, because Go is GCed while C is not. But it would be very surprising if there were no bugs at all in the Go implementation.
What could go wrong with this, right?
/s
The reason I'm so avoidant to using C libraries at all cost is that the ecosystem doesn't prioritize maintenance or other forms of code quality in its distribution. If you have to go to great lengths of having e.g. header only libraries, then what's the point of using C99/C++ at all? Back when conan came out I had hopes for it, but meanwhile I gave up on the ecosystem.
Don't get me wrong, Rust is great for its use cases, too. I just chose the mutex hell as a personal preference over the wrapping hell.
Examples that come to mind: queues that are manipulated inside a loop, slice calls that forget to do length-- of the variable they set in the begin statement, char arrays that are overflowing because the loop doesn't check the length at the correct position in the code, conditions that are re-set inside the loop, like a min/max boundary that is set by an outer loop.
This kind of stuff. I guess you could argue these are memory safety issues. I've seen so crappy loop statements that the devs didn't bother to test it because they still believed they were "smart code", even after sending the devs a PoC that exploited their naive parser assumptions.
In Go I try to write clear, concise and "dumb" code so that a future me can still read it after years of not touching it. That's what I understand under Go's maintainability idiom, I suppose.
While Go isn't perfect and you can certainly write some logic bugs that sufficiently clever use of a more strongly-typed language might let you avoid (though don't underestimate what sufficiently clever use of what Go already has can do for you either when wielded with skill), it has a number of characteristics that keep it somewhat safer than a lot of other languages.
First, it's memory safe in general, which obviously out of the gate helps a lot. You can argue about some super, super fringe cases with unprotected concurrent access to maps, but you're still definitely talking about something on the order of .1% to .01% of the surface area of C.
Next, many of the things that people complain about Go on Hacker News actually contribute to general safety in the code. One of the biggest ones is that it lacks any ability to take an string and simply convert it to a type, which has been the source of catastrophic vulnerabilities in Ruby [1] and Java (Log4Shell), among others. While I use this general technique quite frequently, you have to build your own mechanism for it (not a big deal, we're talking ~50 lines of code or so tops) and that mechanism won't be able to use any class (using general terminology, Go doesn't have "classes" but user-defined types fill in here) that wasn't explicitly registered, which sharply contains the blast radius of any exploit. Plus a lot of the exploits come from excessively clever encoding of the class names; generally when I simply name them and simply do a single lookup in a single map there isn't a lot of exploit wiggle room.
In general though it lacks a lot of the features that get people in trouble that aren't related to memory unsafety. Dynamic languages as a class start out behind the eight-ball on this front because all that dynamicness makes it difficult to tell exactly what some code might do with some input; goodness help you if there's a path to the local equivalent of "eval".
Go isn't entirely unique in this. Rust largely shares the same characteristics, there's some others that may qualify. But some other languages you might expect to don't; for instance, at least until recently Java had a serious problem with being able to get references to arbitrary classes via strings, leading to Log4Shell, even though Java is a static language. (I believe they've fixed that since then but a lot of code still has to have the flag to flip that feature back on because they depend on it in some fundamental libraries quite often.) Go turns out to be a relatively safe security language to write in compared to the landscape of general programming languages in common use. I add "in common use" and highlight it here because I don't think it's anywhere near optimal in the general landscape of languages that exist, nor the landscape of languages that ought to exist and don't yet. For instance in the latter case I'd expect capabilities to be built in to the lowest layer of a language, which would further do great, great damage to the ability to exploit such code. However no such language is in common use at this time. Pragmatically when I need to write something very secure today, Go is surprisingly high on my short list; theoretically I'm quite dissatisfied.
[1]: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-br...
Of course Golang and rust are apples to oranges comparison but still, if someone experienced in golang were to say port to QuickJS to golang and same for rust, aside from some performance cost which can arise from Golang's GC, what would be the security analysis of both?
Also Offtopic but I love how golang has a library for literally everything mostly but its language development ie runtime for interpreted langs/JIT's or transpilation efforts etc. do feel less than rust.
Like For python there's probably a library which can call rust code from Python, I wish if there was something like this for golang and I had found such a project (https://github.com/go-python/gopy) but it still just feels a little less targeted than rust within python which has libraries like polars and other more mature libraries
(The quickjs package in the sibling comment is the original compiled into C. It will probably have all the security quirks of the original as a result.)
But if you are using a VM, you don't even need the Linux kernel: some systems let you compiler your program to run directly on the hypervisor.
See eg https://github.com/hermit-os/hermit-rs or https://mirage.io/
Exactly. "can't translate to safe Rust" is not a good faith argument.
(I’m not trying to be facetious or troll or whatever. Stuff like this is what motivated me to do it.)
Wouldn't GP's approach work with any other executable using libc? Python, Node, Rust, etc?
I fail to see what is specific to either C or QuickJS in the GP's approach.
> Yikes.
Yep.
Probabilistic mitigations work against probabilistic attacks, I guess - but exploit writers aren't random, they are directed, and they find the weaknesses.
"This is true by definition as the QuickJS vulnerability was previously unknown until I found it (or, more correctly: my Opus 4.5 vulnerability discovery agent found it)."
https://github.com/nobodyisnobody/docs/blob/main/code.execut...
Original publication in 2017:
https://m101.github.io/binholic/2017/05/20/notes-on-abusing-...
Lots of vulnerabilites get stopped dead by these mitigations. You almost always need multiple vulnerabilities tied together, which relies on a level of vulnerability density that's tractable. This is not just busywork.
Reports about the ones that are exploitable usually read to me like after finding an entry, the attacker reaches into the well-stocked toolbox of post-entry techniques (return-oriented programming, nop slides, return to libc...) to do the rest of the work.
I hope not, my laptop is slow enough as it is.
WASM adds a layer, but the first thing anyone will do is look for a way to escape it. And unless all software faults and hardware faults magically disappear, it'll still be a constant source of bugs.
Pitching a sandbox against ingenuity will always fail at some point, there is no panacea.
[0] https://instatunnel.substack.com/p/the-wasm-breach-escaping-...
I still doubt they will hook up their brains though.
The interesting part is still finding new potential RCE vulnerabilities, and generally if you can demonstrate the vulnerability even without demonstrating an E2E pwn red teams and white hats will still get credit.
We need new platforms which provide the necessary security guardrails, verifiability, simplicity of development, succinctness of logic (high feature/code ratio)... You can't trust non-technical vibe coders with today's software tools when they can't even trust themselves.
There are other nuances which may offset the asymmetry a bit; for example the security analyst generally has much more visibility over the company's code than the hacker does.
That said, I stand by my original point because I think that building secure systems is really hard; it's much more effort per unit of functionality to build the system correctly (and doing that for every part of it) than it is to crack it (by finding a single hole).
On the side of defense, you need to understand a lot of nuance about how your system works and how parts interact to make it secure; any neglect can potentially be a critical vulnerability which can compromise the entire system.
On the side of offense, sometimes mindless prodding can uncover a critical vulnerability. The intelligence/thinking requirement is lower; it's more about knowledge than thinking.
For example, there are some special payloads which you can send which may pose a problem for different systems built by different companies because the companies share the same underlying engine or they fell victim to the same footgun. I think this aspect is much more important than my previous argument.
The reflects my experience too. Opus 4.5 is my everyday driver - I like using it. But Codex 5.2 with Extra High thinking is just a bit more powerful.
Also despite what people say, I don't believe progress in LLM performance is slowing down at all - instead we are having more trouble generating tasks that are hard enough, and the frontier tasks they are failing at or just managing are so complex that most people outside the specialized field aren't interested enough to sit through the explanation.
Gemini either does a Monet or demolishes your bathroom and builds a new tuna fishing boat there instead, and it is completely random which one you get.
It's a great model but I rarely use it because it's so random as to what you get.
If forking is blocked, the exit handler can't do it either. If it's some variant of execve, the sandbox is preserved so we didn't gain much.
Edit: ok, I get it! Missed the "Goal: write exactly "PWNED" to /tmp/pwned". Which makes the sandbox part way less interesting as implemented. It's just saying you can't shell out to do it, but there's no sandbox breakout at any point in the exploit.
I actually think this result is a little disappointing but I largely chalk it up to the limited budget the author invested. In the CTF space we’re definitely seeing this more and more as models effectively “oneshot” typical pwn tasks that were significant effort to do by hand before. I feel like the pieces to do these are vaguely present in training data and the real constraints have been how fiddly and annoying they are to set up. An LLM is going to be well suited at this.
More interestingly, though, I suspect we will actually see software at least briefly get more secure as a result of this: I think a lot of incomplete implementations of mitigations are going to fall soon and (humans, for now) will be forced to keep up and patch them properly. This will drive investment in formal modeling of exploits, which is currently a very immature field.
Can you elaborate more on this with pointers to some resources?
I think the main challenge for hackers is to find 0day vulnerabilities, not writing the actual exploit code.
>This is true by definition as the QuickJS vulnerability was previously unknown until I found it (or, more correctly: my Opus 4.5 vulnerability discovery agent found it).
1) it becomes increasingly more dangerous to dl stuff from the internet and just run it, even its opensource, given normally people don't read all of it. for weird repos I'd recomment to do automated analysis with opus 4.5 or the gpt 5.2 indeed.
2) if we assume adversaries are using LLMs to churn exploits 24/7, which we should absolutely do, perhaps the time where we turn the internet off whenever is not needed, is not far.
You are right: 30 years ago, it was safe to go to vendor XY page and download his latest version and it was more or less waterproof. Today with all these mirror sites, very often better SEO ranking than the original, its quite dangerous: In my former bank we had a colleague who installed a browser add-in that he used for years (at home and in the bank); then he got a new notebook, fresh browser, he installed the same extension - but from a different source than the original vendor: unfortunately, this version contained malware and a big transaction was caught by compliance in the very last second, because he wasnt aware of data leakage.
You _are_ joking, right? I distinctly remember all sorts of dubious freewarez sites with slightly modified installers. 1997-2000 era. And anti-virus was a thing in MS-DOS even.
but, you are old enough - so mean pages like fosi.da.ru back then? ;-)
The industrialization of exploit generation is here IMO.
protocolture•2w ago
simonw•2w ago
The quality of output you see from any LLM system is filtered through the human who acts on those results.
A dumbass pasting LLM generated "reports" into an issue system doesn't disprove the efforts of a subject-matter expert who knows how to get good results from LLMs and has the necessary taste to only share the credible issues it helps them find.
anonymous908213•2w ago
[1] If their experiment even demonstrates what it purports to demonstrate. For anyone to give this article any credence, the exploit really needs to be independently verified that it is what they say it is and that it was achieved the way they say it was achieved.
GaggiX•2w ago
simonw•2w ago
IanCal•2w ago
1. I think you have mixed up assistance and expertise. They talk about not needing a human in the loop for verification and to continue search but not about initial starts. Those are quite different. One well specified task can be attempted many times, and the skill sets are overlapping but not identical.
2. The article is about where they may get to rather than just what they are capable of now.
3. There’s no conflict between the idea that 10 parallel agents of the top models can mostly have one that successfully exploits a vulnerability - gated on an actual test that the exploit works - with feedback and iteration BUT random models pointed at arbitrary code without a good spec and without the ability to run code, and just run once, will generate lower quality results.
adw•2w ago
This applies to exploits, but it applies _extremely_ generally.
The increased interest in TLA+, Lean, etc comes from the same place; these are languages which are well suited to expressing deterministic success criteria, and it appears that (for a very wide range of problems across the whole of software) given a clear enough, verifiable enough objective, you can point the money cannon at it until the problem is solved.
The economic consequences of that are going to be very interesting indeed.
protocolture•2w ago
simonw•2w ago
moyix•2w ago
> I have written up the verification process I used for the experiments here, but the summary is: an exploit tends to involve building a capability to allow you to do something you shouldn’t be able to do. If, after running the exploit, you can do that thing, then you’ve won. For example, some of the experiments involved writing an exploit to spawn a shell from the Javascript process. To verify this the verification harness starts a listener on a particular local port, runs the Javascript interpreter and then pipes a command into it to run a command line utility that connects to that local port. As the Javascript interpreter has no ability to do any sort of network connections, or spawning of another process in normal execution, you know that if you receive the connect back then the exploit works as the shell that it started has run the command line utility you sent to it.
It is more work to build such "perfect" verifiers, and they don't apply to every vulnerability type (how do you write a Python script to detect a logic bug in an arbitrary application?), but for bugs like these where the exploit goal is very clear (exec code or write arbitrary content to a file) they work extremely well.
doomerhunter•2w ago
The AI slop you see on curl's bug bounty program[1] (mostly) comes from people who are not hackers in the first place.
In the contrary persons like the author are obviously skilled in security research and will definitely send valid bugs.
Same can be said for people in my space who do build LLM-driven exploit development. In the US Xbow hired quite some skilled researchers [2] had some promising development for instance.
[1] https://hackerone.com/curl/hacktivity [2] https://xbow.com/about
ronsor•2w ago
rvz•2w ago
tptacek•2w ago
simonw•2w ago
His co-founder on optimyze was Sean Heelan, the author of the OP.
tptacek•2w ago
0xbadcafebee•2w ago
rwmj•2w ago
With the CVE reports some poor maintainer has to go through and triage them, which is far more work, and very asymmetrical because the reporters can generate their spam reports in volume while each one requires detailed analysis.
SchemaLoad•2w ago
simonw•2w ago
An "agent harness" here is software that directly writes and executes code to test that it works. A vulnerability reported by such an agent harness with included proof-of-concept code that has been demonstrated to work is a different thing from an "exploit" that was reported by having a long context model spit out a bunch of random ideas based purely on reading the code.
I'm confident you can still find dumbasses who can mess up at using coding agent harnesses and create invalid, time wasting bug reports. Dumbasses are gonna dumbass.
staticassertion•2w ago
wat10000•2w ago
NitpickLawyer•2w ago
The proper way to use these tools (like in other verifiable tasks such as math or coding) is to give them a feedback loop and an easily verifiable success criteria. In security exploitation you either capture the flag or not. It's very easy (and cheap) to verify. So you can leave these things to bang their tokens against a wall, and only look at their output once they capture the flag. Or they output something somewhere verifiable (e.g. echo "pwned" > /root/.flag)
GrinningFool•2w ago
airza•2w ago
pixl97•2w ago
rwmj•2w ago
0xDEAFBEAD•2w ago
ares623•2w ago
0xDEAFBEAD•2w ago
Note I haven't actually tried Claude Code (not coding due to chronic illness), so I'm mostly extrapolating based on HN discussion etc.
0xDEAFBEAD•2w ago
Another thought is the reproducible builds become more valuable than ever, because it actually becomes feasible for lots and lots of devs to scan the entire codebase for vulns using an LLM and then verify reproducibility.
QuadmasterXLII•2w ago
tptacek•2w ago
QuadmasterXLII•2w ago
pjc50•2w ago
AdieuToLogic•2w ago
For an interesting overview of the above theorem, see here[1].
0 - https://en.wikipedia.org/wiki/Infinite_monkey_theorem
1 - https://www.yalescientific.org/2025/04/sorry-shakespeare-why...
wat10000•2w ago
octoberfranklin•2w ago
GoatInGrey•2w ago
raesene9•2w ago
For example if you just ask an LLM in a browser with no tool use to "find a vulnerability in this program", it'll likely give you something but it is very likely to be hallucinated or irrelevant.
However if you use the same LLM model via an agent, and provide it with concrete guidance on how to test its success, and the environment needed to prove that success, you are much more likely to get a good result.
It's like with Claude code, if you don't provide a test environment it will often make mistakes in the coding and tell you all is well, but if you provide a testing loop it'll iterate till it actually works.
_factor•2w ago