You can't bug fix your way out of the vulnpocalypse
(I work for Anthropic.)
One of the most important (and hardest!) questions for a security engineer to answer is “how many vulnerabilities exist in this code base”. You can know how many vulnerabilities you are aware of but haven’t patched yet. You might be able to do some arithmetic and estimate based on historical vulnerability time between introducing and discovery how many vulnerabilities exist, but are undiscovered, but that’s harder. Despite the inherently high level of uncertainty in answering just how many vulnerabilities exist, but are unknown, we all have a tendendecy to assume the rate of newly discovered vulnerabilities yesterday will also be true tomorrow. But some days you wake up and discover you’re no longer in Kansas. I remember when coverage-guided fuzzing (AFL and libFuzzer) got good enough that basically anything you could make parser-shaped was sure to produce a fair number of vulnerabilities. And now the AI vulnpocalypse has arrive, and for good measure it can also produce working exploits.
The recipe for a vulnpocalypse is a new technological innovation enables (or indirectly results in) finding a very large number of vulnerabilities in pre-existing software, which renders all previous assumptions and beliefs about the volume of extant vulnerabilities incorrect. When the vulnpocalypse hits, companies, open source projects, and software consumers are saddled with the task of identifying, triaging, fixing, distributing, and patching at a massively accelerated pace. Because there are so many vulnerabilities, existing processes break down. It ceases to become possible to fix all of the vulnerabilities with the pre-existing resource allocations and procedures.
This pattern – of new technological innovation upsetting core assumptions and requiring new approaches – is an example of what the literature calls “fundamental surprise”, and some friends of mine wrote a book about this. The failure mode of a vulnpocalypse is that the pile of vulnerabilities grows too tall, the triage process falls too far behind, open source maintainers burn out, and fixing the vulnerabilities becomes an exercise in random sampling and praying that the missed vulnerabilities don’t get exploited. Some teams double down on fixing the vulnerabilities one by one, driving out other types of projects they could work, and simply trying to patch anything they can find until they reach the status quo ante vulnerability equilibrium. These are really two sides of the same coin, simply with different levels of success.
Fortunately, there’s a better way. It begins with the recognition that a huge volume of vulnerabilities have substantially the same shape and proximate cause, and are amenable to systemic fixes. Not every vulnerability, but a lot of them.
Many years ago, I was pulled in to assist a team who was dealing with their own personal vulnpocalypse. It was an old VB Script codebase, a few hundred thousand lines of code, and a team of developers in maintenance mode. It was the kind of codebase where literally every SQL statement was vulnerable to SQL injection and every single variable incorporated into the HTML was an XSS vulnerability. There were other vulnerabilities as well, but by sheer volume, XSS and SQLi were easily 90%+ of them.
The pattern of SQLi was a common one in older applications: every page had its own bespoke code for opening a database connection and SQL was hand-crafted with string concatenation. The approach to fixing this was not to hand review every SQL query for whether it was vulnerable, it was to introduce a new SQLExecute function which took a SQL query and an array of parameters, and handled the query correctly. Then every single SQL query in the codebase was migrated to SQLExecute (many by a simple regular expression). Afterwards, a simple rule ensured there would be no regressions: it was illegal to execute a SQL query in any other way besides calling SQLExecute with a string literal, a rule that could be trivially enforced in CI. The net result was fixing thousands of vulnerabilities in a matter of a week or two, and the vulnerabilities staying fixed, and not being reintroduced.
This pattern of restricting a codebase to only safe patterns is not a novel one. To prevent XSS, Django’s templates automatically HTML escape any variables interpolated into a template, and React distinguishes between textual content and markup. It’s memory safe languages' approach to preventing buffer overflows and use-after-free vulnerability. Unfortunately, far too frequently, it’s not the approach people reach for.
One common objection to this way of thinking is, “That’s all well and good, but I’m too underwater to keep up with the simple bug fixes, and now you want me to take the time to make huge technical changes?” It’s a very reasonable question. The nature of a vulnpocalypse is that you’re going to be drowning in the deluge of the vulnerabilities – if you weren’t, it wouldn’t be a vulnpocalypse! Given that background, you need to step back and ask “how do we get out of this situation?” And the answer is that you make foundational investments in systemic prevention of entire classes of vulnerabilities, even at the expense of having marginally high latency to fixing individual vulnerabilities. While in the very short run this can be painful, on longer time scales, it’s essential. And of course, like any good engineering project you should structure you work towards incremental deliverables that add value, not one giant big-bang that won’t materialize for forever.
At a fundamental level, many people have an incorrect notion of what the point of vulnerability research is in a software development life cycle. The point of vulnerability research (by which I mean anything that identifies vulnerabilities after a pull-request has already been merged) is to identify gaps in your tooling and abstractions so you can improve them. Identifying individual bugs for you to fix is the mechanism by which you find those gaps, and it’s valuable because the presence of a vulnerability is a proof-by-existence of the gap. If all you do with the vulnerabilities identified by security research is fix them, you’re wasting a huge opportunity.
Not every vulnerability is amenable to a neat “simply prevent all possible instances of it” resolution. However, effectively every vulnerability can have the likelihood of its recurrence dramatically reduced by improvements to tools and abstractions. And vulnerabilities that are amenable to systemic fixes are depressingly common. Looking at the 2025 top causes of Known Exploited Vulnerabilities, all of the top three, and six of the top ten, are amenable to systemic fixes.
If you see the vulnpocalypse coming for you, the most important thing you can do is channel it into systemic fixes. The alternative is letting a crisis go to waste, and drowning under the weight of a massive number of vulnerabilities.