The productivity claims about AI coding assistants are real, and nobody who uses them daily needs a study to believe it. What changed in the last year is that enough generated code has shipped for people to start counting the other side of the ledger. The numbers are specific enough to be useful, and more interesting than "AI code is insecure". It fails in particular places, for a particular reason, and once you see the pattern you know where to look.
This is not an argument against the tools. I use them every day. It is an argument about who checks the output, and which parts of it deserve checking first.
The numbers, read carefully
Veracode has been running the same test for a while now: give a large set of models security-sensitive coding tasks, with no security guidance in the prompt, and scan what comes back. Its Spring 2026 update covers more than 150 models. Across all of them, the security pass rate sits at 55%, which means that in roughly 45% of cases the model chose an insecure way of doing the job when a secure one was available.
The average hides the interesting part, which is how uneven it is. Cross-site scripting (CWE-80) passes only 15% of the time. Log injection (CWE-117) passes 13% of the time. SQL injection, the vulnerability everybody learned to fear first, passes 82% of the time. By language, Java is worst at a 29% pass rate, and Python is best at 62%, with JavaScript and C# in between at 57% and 58%.
Two more findings from the same report matter more than any single percentage. Model size has only a very small effect on security performance, and that small difference has largely disappeared in recent releases. And the flagship 2026 models did not move the number: they cluster around the same 55%, within the margin of error of the earlier ones. If you have been waiting for the next model to fix this, the data says it is not coming from that direction.
Why SQL injection got fixed and XSS did not
A model writes the most probable code for the request, and the most probable code is whatever dominates the examples it learned from. That one sentence explains the whole table.
SQL injection passes 82% of the time because the modern examples are overwhelmingly parameterised. Every ORM tutorial, every query builder, every "connect Node to Postgres" post of the last ten years uses placeholders, so the probable code is the safe code. The industry fixed the training data years before anyone trained on it.
Cross-site scripting is the opposite case. Whether a string is dangerous depends on where it lands: an HTML body, an attribute, a URL, a script block. The model generating the handler usually does not know, and the tutorial it is echoing did not care, because a tutorial demonstrates a feature rather than a defence. This is the kind of thing that comes back when you ask for a quick search endpoint:
app.get('/search', (req, res) => {
const q = req.query.q
const results = searchProducts(q)
res.send(`<h1>Results for ${q}</h1>${renderList(results)}`)
})
It works. It passes the test you actually wrote, which is whether searching for "shoes" returns shoes. It also reflects whatever is in q straight into the page. The fix is not clever, it is just the part the example left out: render through a templating layer that escapes by default, or escape explicitly at the point where the string enters HTML.
Log injection is the purest version of the problem, because almost nobody writes tutorials about logging safely. So the model writes what everybody writes:
logger.info(`Login failed for user ${username}`)
Put a newline and a fake timestamp into username and you can forge entries in the log that incident response will later trust. The fix is structured logging, where user data is a field rather than part of the message:
logger.info({ username }, 'login failed')
None of this is the model making a mistake by its own standards. It is reproducing the distribution it learned, and that distribution is mostly demonstrations. That is also the most plausible reading of why Java comes out worst: a very large, very old body of example code written before most of today's defaults existed.
Where the velocity number hides the risk
The other study worth knowing is Apiiro's, which looked at tens of thousands of repositories and several thousand developers inside Fortune 50 companies. AI-assisted developers produced three to four times as many commits as their peers, packaged into fewer pull requests, each one larger and touching more files and services per change. By June 2025, AI-generated code was introducing more than 10,000 new security findings a month across the repositories studied, ten times the December 2024 level.
The breakdown is what makes it worth reading. Trivial syntax errors dropped by 76% and logic bugs by more than 60%. At the same time, privilege escalation paths rose 322% and architectural design flaws rose 153%. The Register's coverage of the same research adds that developers relying on AI exposed cloud credentials and keys nearly twice as often.
Put those together and the shape is clear. The bugs did not go away, they moved. They moved out of the category that a compiler, a linter or a failing test catches for free, and into the category that only a reviewer who stops and thinks will catch. And they arrived in larger pull requests, which is exactly the format in which reviewers stop and think least. Nobody reads a 40-file diff with the same attention as a 4-file one.
The CVE curve
Georgia Tech's Systems Software and Security Lab runs a project called Vibe Security Radar, which attributes published CVEs to AI-generated code where the evidence allows it. The counts for early 2026 were six in January, fifteen in February and thirty-five in March, a near sixfold rise in two months and 74 confirmed cases overall.
The researchers are explicit that this is a floor rather than an estimate. Most generated code carries no metadata that would let anyone attribute it, and most flaws that get found and patched never receive a CVE at all. Their own assessment is that the real figure across public open source is five to ten times higher. The absolute numbers are still small. The slope is the point.
What I actually do about it
Nothing here requires slowing down. It requires putting the checks where the failures are, which the numbers above make fairly specific.
The first line of defence is choosing tools whose defaults are safe, so the probable code and the safe code are the same code. React and Next.js escape interpolated strings in JSX by default, which removes most reflected XSS before anyone types a prompt. That is part of why we build client sites on Next.js. The escape hatch is then the only thing you have to watch, and it is easy to find:
grep -rnE "dangerouslySetInnerHTML|\.innerHTML\s*=|v-html" src/
Every hit is a place where someone, or something, decided to bypass the default. Some of those decisions are right. All of them deserve a human look.
The second is automation in the pipeline rather than at audit time. A static analysis step such as CodeQL or Semgrep on every pull request, plus a secret scanner before commit, surfaces the findings when the change is still small and its author still remembers writing it. Given the credential numbers above, the secret scanner is the cheapest single control on this list.
The third is deciding in advance which code always gets a human reviewer, regardless of who or what wrote it: anything touching input handling, authentication, authorisation, data access or logging. That is a small share of most codebases and most of the risk, and it maps almost exactly onto where the Veracode failures cluster and where Apiiro's privilege escalation paths come from.
The fourth is a rule more than a tool. Generated code is a draft. It gets read before it is merged, and a pull request that is too large to read gets split rather than skimmed. Apiiro's finding about larger pull requests is, in the end, a finding about review, and it is the one that is entirely in our hands.
It is also worth remembering that the Veracode numbers come from prompts with no security guidance at all. That is the condition most generated code is produced under, because most prompts are about the feature. Saying in the prompt that input must be treated as hostile costs nothing, though the report is a measurement of the default, not a promise about what a better prompt achieves.
The client side of this
There is one more reason this matters beyond our own repositories. A lot of cheap web work is now produced very quickly, and the visible layer, meaning the pages, forms and layout, is exactly what these tools do well. A site can look entirely finished and still carry a search box that reflects a script tag. The person who paid for it has no way to tell from the outside.
The cheapest moment to find that is before launch. The most expensive is after somebody else finds it for you.
The original
This is the longer, developer-side version of a short piece on our site, written for the people buying websites rather than building them. The original sets out what these studies mean if you bought a cheap build, and answers the questions clients ask about it: whether to stop using AI assistants, whether a brochure site is affected, and whether code written by a person is automatically safer.
AI writes code four times faster. And bugs ten times faster.
This copy is a snapshot from the day it was posted, and it will not be updated here. The original on our site is the version we keep current: when a study publishes new figures, a price changes or a tool is renamed, that is where the correction lands. If you want the up-to-date version, follow the link above.
Sources
The model test figures, including the pass rates by vulnerability class and language, the 150-model scale and the findings on model size and 2026 releases, are from Veracode's Spring 2026 GenAI code security update. The commit, pull request and findings figures are from Apiiro's 4x Velocity, 10x Vulnerabilities, and the credential exposure figure is from The Register's coverage of the same research. The CVE counts and the undercount estimate are from the Cloud Security Alliance's research note Vibe Coding's Security Debt, which reports Georgia Tech's Vibe Security Radar data. The code examples and the reading of why the failures cluster where they do are my own.
Which of these have you actually caught in review, and which one only turned up after it shipped?