All posts
Engineering·April 13, 2026·8 min

What AI-generated code gets wrong about security

What AI-generated code gets wrong about security

AI coding assistants are extraordinary at producing code that works. They are notably worse at producing code that is safe, and this is not a hunch, it is one of the better-measured findings in software security right now. Safety lives in the things that never show up when the happy path runs: the authorization check, the input nobody pastes into a demo, the quiet assumption that the caller is who they claim to be. Those are exactly the things a model trained to produce plausible, working code tends to skip.

The research is unusually consistent

Start with the controlled experiment. In a Stanford study presented at ACM CCS 2023, Do Users Write More Insecure Code with AI Assistants?, developers given an AI assistant wrote less secure code than those without one across most of the tasks. The detail that should keep you up at night is the second finding: the people using the assistant were also more confident that their code was secure. The tool did not just introduce more bugs, it introduced more bugs while making the author feel safer.

Then the scale studies. NYU researchers, in Asleep at the Keyboard?, had GitHub Copilot complete 89 security-relevant scenarios and found that roughly 40% of the 1,689 programs it produced contained a vulnerability from MITRE's Top 25 weakness list. More recently, Veracode's 2025 GenAI Code Security Report tested more than 100 models and found that 45% of generated samples introduced an OWASP Top 10 weakness. The most uncomfortable line in that report: newer, larger models were not meaningfully safer than older ones. The code got more fluent. It did not get more secure.

A bug you can see gets fixed. The dangerous ones ship behind the feeling that the code was already done.

The same failure modes, over and over

Because the cause is structural, the symptoms are predictable. Across AI-built codebases the same categories appear again and again, since the model optimizes for code that looks right and runs, not code that survives an adversary.

  • Missing object-level authorization (IDOR): the endpoint fetches a record by id and forgets to scope it to the caller's tenant or user.
  • Trusting client-controlled data: roles, prices, or feature flags read from the request instead of being re-derived on the server.
  • Secrets in the bundle: keys and tokens inlined into the client because that is what made the demo work.
  • Inconsistent input handling: one route sanitizes its input, the adjacent route, generated from a different prompt, does not.
  • Auth flows that are good enough to ship: no rate limiting, weak session handling, verbose errors that leak structure.

Why it scales the way it does

A human writes one IDOR by accident on a tired afternoon. An assistant writes the same shape of endpoint fifty times in an afternoon, each with the same omission, because it is reproducing a pattern rather than reasoning about a threat. The vulnerability stops being a one-off and becomes a template, stamped out wherever the pattern was reused. This is why AI-built applications tend to fail in clusters: find one instance of a class, and there are usually a dozen more with the same fingerprint.

It is worth being precise about what is happening, because the headline writes itself wrong. AI is not inventing exotic new vulnerability classes. It is mass-producing the old, well-understood ones at a speed that human review was never built to keep up with. The OWASP Top 10 did not change. The rate at which a small team can generate instances of it did.

The overconfidence tax

The Stanford overconfidence result deserves its own beat, because it changes how you should think about review. If AI-assisted code felt risky, teams would scrutinize it harder. Instead it feels finished, it compiles, it passes the tests the same assistant helpfully wrote, and it ships. The feeling of safety is itself a vulnerability, because it removes the friction that would otherwise trigger a closer look. The result is faster delivery of code that nobody adversarially examined.

What actually closes the gap

The answer is not to stop building with AI. That ship has sailed, and the productivity is real. The answer is to test like an adversary at the same speed and scale you build, so that the testing keeps pace with the generation instead of falling a year behind it. The mistakes are predictable, which means they are findable. The job is to go looking for them deliberately, prove the ones that are real with a working exploit, and do it on every release rather than once a year.

That predictability is exactly what Uvy is built to exploit. We test AI-built applications for the specific, repeating mistakes that AI-built applications make, back the real ones with a working exploit instead of a flag, and run with the cadence the code is actually shipped at. See how it works.

Find every way in, before an attacker does

Uvy runs continuous offense and defense across your applications at machine speed, and hands your team proof and the exact fix. Start a pentest yourself, or talk to us about scope.

Free to test. No card to start.

Or write to [email protected]