Back to all posts
Research

Your Model Got Smarter. Your Code Did Not Get Safer.

Capability doubled in one model generation while security stayed flat. Why upgrading the model and telling it to be secure both fail under measurement.

On this page
  1. Capability is compounding. Security is flat.
  2. Why upgrading the model is not a security control
  3. Why telling the model to be secure is not a control either
  4. What the benchmarks measure, and what they cannot
  5. The three failure modes a model upgrade does not touch
  6. Business logic, which has no benchmark and no signature
  7. The agent's actions, which are a separate attack surface
  8. The dependencies it chooses
  9. Model upgrade versus enforcement, side by side
  10. What actually works: enforcement over instruction
  11. Frequently asked questions
  12. Does a newer AI model write more secure code?
  13. Which model writes the most secure code?
  14. Does telling the model to write secure code help?
  15. If prompting does not work, why do rules in the agent context matter at all?
  16. Are the security benchmarks trustworthy?
  17. Should we stay on an older model for safety reasons?
  18. Does this mean AI-generated code cannot be shipped safely?
  19. What single metric should we track instead of a model's security score?

Two curves on the same axis: agent capability climbing steeply across model generations while the security pass rate stays flat, with an enforcement gate closing the gap.

In one generation, Claude Opus 5 went from 18.7% to 43.3% on FrontierBench v0.1. Claude Fable 5 sits at roughly 95% on SWE-bench Verified. Agentic coding capability is not improving gradually, it is compounding. So the reasonable assumption, the one every engineering leader we talk to has made at least once, is that security rides along for free: a model good enough to solve 95% of real tasks surely knows better than to concatenate a SQL string. It does know better. It still does it. And the two obvious responses, upgrade to the newest model and tell it to be careful, have both now been measured. Both fail. This article is about why, and about what a control has to look like once you accept that.

Capability is compounding. Security is flat.

Start with the part that is genuinely impressive, because the argument does not work if you pretend the models are bad.

On FrontierBench v0.1, Claude Opus 5 scores 43.3% at maximum effort, against 18.7% for Opus 4.8, 33.7% for Fable 5 and 37.5% for GPT-5.6 Sol. That is more than a doubling between two Opus releases. On SWE-bench Verified, Fable 5 is around 95%, and SWE-bench Pro, the harder set, is at roughly 80%. Whatever you thought an agent could not do eighteen months ago, it probably can now.

Now put the security curve on the same axis. Multiple independent measurements, academic and industrial, converge on the same shape: syntax correctness above 95%, task success in the eighties and nineties, and the share of generated code that passes a security check stuck near the middle of the range, essentially where it sat two years ago. The lines diverge.

Every model generation buys you more capability. No model generation has bought you meaningfully more security.

- The uncomfortable shape of the data

The reason is not mysterious once you look at how the models are trained. Functional correctness has a clean reward signal: the tests pass or they do not, the benchmark scores or it does not. You can optimize that with gradient descent and a leaderboard. Security has no equivalent signal. It is a non-functional property, it is expensive to label, the absence of a vulnerability looks identical to the absence of a check, and the failure surfaces months later in an incident nobody attributes back to the training run. Whatever the optimization pressure is pointing at, it is not pointing at that.

There is a second, subtler reason visible in the training data. Some vulnerability classes have decades of well-documented, endlessly repeated fix patterns in public code: SQL injection, weak cryptography, path traversal. Models handle those comparatively well because the safe pattern is the statistically common pattern. The classes that depend on knowing something about the runtime, the operating system, the tenant model or the business rule have no such corpus. They are not underrepresented in the training data so much as absent from it.

We covered the general state of the problem in is AI-generated code safe. This article is the narrower and more actionable question: given that state, does changing the model or changing the prompt do anything about it?

Why upgrading the model is not a security control

The honest answer is that a newer model does help a little, and not in the way people assume.

What improves with a model upgrade is the ability to produce code that works, and the ability to reason about security when you ask about it directly. That second part is the one worth sitting with, because it is where the mechanism of the failure becomes visible. Models can frequently identify the correct defensive measure when you pose it as a question. Then they write the final code and omit it. The gap is not a knowledge gap, it is an execution gap. The model is not confused about whether user input should be parameterised; it is optimising, at generation time, for the thing that looks like a completed task.

That distinction matters commercially, because it predicts which purchases will disappoint you. Buying a smarter model to reduce vulnerability density is buying against the wrong variable. You will get more working code per hour, which means more code per hour, which means more of whatever your vulnerability rate is per hour. If the rate is flat and the volume triples, your absolute exposure triples. Capability without a corresponding control is throughput, and throughput is not safety.

Model choice does have a real effect on one axis: how much verification load you carry. A model that gets the injection classes right most of the time leaves you fewer of those to catch. That is a genuine efficiency gain. It is not a control, because it is probabilistic, unaudited, and it changes silently every time the vendor ships a new checkpoint.

Why telling the model to be secure is not a control either

This is the part that most vendor content gets wrong, including, if we are honest, the lazy version of our own pitch. If you have read that the answer is "just put security instructions in the context", the evidence does not support it.

The clearest measurement to date is "An Empirical Evaluation of LLM-Generated Code Security Across Prompting Methods" by Mohammed Kharma, Ahmed Sabbah, Mohammad Alkhanafseh, Mohammad Hammoudeh and David Mohaisen, submitted to arXiv on 22 May 2026. They evaluated five LLMs across four languages, Java, C++, C and Python, under multiple prompt engineering methods, and they built a deliberately favourable one for the security case: a weaknesses-aware zero-shot chain-of-thought that enriches the prompt with security context using CWE mappings to steer the model's reasoning.

Their result, supported by chi-square tests, is stated plainly in the abstract: no statistically significant reductions in vulnerability frequency or density across prompt methods. What the prompting strategies did change was the compositional distribution of CWE categories, with the effect varying by language. In other words, security-aware prompting reshuffles which weaknesses you get. It does not reduce how many you get.

The companion finding is arguably worse for the prompt-as-control theory. "Minimal Prompt Perturbations Lead to Code Vulnerabilities: Prompt Fragility and Hidden-State Signals in Coding LLMs", arXiv, 29 May 2026, shows that small and benign modifications to a prompt, adding a comment, rephrasing an instruction, inserting innocuous text, reliably push coding models back into generating vulnerable code. Not adversarial jailbreaks. Ordinary edits of the kind that happen a hundred times a day in a real session.

Read those two results together and a design constraint falls out. You cannot put your security posture in the same channel as the thing you are trying to constrain. If the policy lives in the prompt, it competes for attention with the task, the repository conventions, the file the agent just read and whatever a contributor wrote in a Markdown file. If the policy lives in a gate that evaluates the action, it does not compete with anything.

What the benchmarks measure, and what they cannot

Before drawing conclusions from benchmark numbers it is worth knowing what they are made of, because the honest reading is narrower than the headlines.

The serious academic benchmarks are good and getting better. CWEval provides a multilingual, security-critical coding benchmark spanning 31 CWE types across five languages, and its contribution is outcome-driven evaluation: it judges functionality and security jointly rather than pattern-matching the output. RealSec-bench is built from real-world, high-risk Java repositories, 105 instances across 19 CWE types, which is a deliberate move away from synthetic snippets. SecureAgentBench pushes further, benchmarking secure code generation under realistic vulnerability scenarios rather than isolated prompts.

All of them share three structural limits that no amount of extra CWE coverage fixes.

They score single-shot generation, not sessions

A benchmark asks for a function and grades the function. A real agent runs for an hour, reads files you did not name, calls tools, accumulates context, and edits across the tree. The unit of risk in production is a session, not a completion. Nothing in the pass rate tells you what happens on turn forty.

They can only test what has a CWE

A benchmark needs a ground truth, so it needs a named weakness class. That structurally excludes the flaws that are specific to your application: a discount that can go negative, an authorisation check that is correct per endpoint and wrong per tenant, a refund path that skips a state transition. There is no CWE for your business rule, so there is no benchmark row for it either.

They grade the code, not the actions

Modern agents do not only write. They execute commands, read credentials files, fetch pages, install packages and open pull requests. A generation benchmark has nothing to say about an agent that writes perfectly safe code and exfiltrates an AWS key in the same session.

None of this is an argument against benchmarks. It is an argument against treating a pass rate as a risk model. A model can top every table in the previous section and still be the proximate cause of your next incident, because your next incident will probably be in the third column of that grid.

The three failure modes a model upgrade does not touch

Concretely, here is what stays exactly as broken after you switch to the newest, highest-scoring model available.

Business logic, which has no benchmark and no signature

The vulnerability classes with decades of public fix patterns are the ones models handle best. Your business rules have zero public fix patterns, because they exist only in your codebase and, frequently, only in the head of whoever specified them. An agent that writes a flawless parameterised query will still happily let a quantity be negative if nothing in the repository told it that quantities are positive. This is the failure mode we consider structurally unfixable by better models, and we wrote it up in business logic flaws in AI-generated code.

The agent's actions, which are a separate attack surface

The moment the agent can run commands, the security question stops being only "is this code correct" and becomes "whose instructions is it following". Repository files like AGENTS.md and CLAUDE.md are loaded as trusted project policy, which makes them a steering channel for anyone who can commit. We documented that mechanism and the named 2026 incidents in instruction file injection. A more capable model makes that worse rather than better, because it executes the hostile plan more competently.

The dependencies it chooses

Models still invent package names, and attackers still pre-register them. A better model hallucinates less often, which reduces frequency without changing the shape of the risk, and one accepted hallucination is enough. See what is slopsquatting.

There is also a fourth item that belongs here even though it is not a code-quality issue, because it is the clearest evidence that capability is genuinely double-edged. Anthropic's own Opus 5 safety card reports the model successfully compromising enterprise networks in eight out of ten government-run tests. Around Fable 5, Amazon researchers found a way to elicit exploit-demonstration code for a software vulnerability, which led Anthropic to redeploy the model with enhanced safety measures on 30 June 2026, and the public Fable 5 now routes detections of cyber, biology, chemistry and model-distillation misuse to a different model. Separately, community reports describe the safety classifier being bypassed in Claude Code by framing a restricted request as a /btw side question, exploiting the gap between the routing logic and the primary session context.

Every one of those is an argument that the frontier is climbing on both sides of the fence at once. None of them is an argument for staying on an older model. They are an argument that the guardrail has to be outside the model.

Model upgrade versus enforcement, side by side

Question
Newer model, better prompt
Enforcement in the loop
Does the vulnerability rate drop?
Flat across generations; no significant effect from prompting methods
The unsafe action is refused before it runs
Is it stable day to day?
A benign added comment can flip generation back to vulnerable
A deterministic gate does not depend on surrounding text
Does it know your business rules?
No public fix patterns exist for them
Rules mined from your own repository
Does it cover the agent's actions?
Generation quality says nothing about tool calls
The tool call is the thing being evaluated
Can you audit why it allowed something?
No record; the model reweighed the context
A logged decision on a named rule
Does it survive the next release?
Behaviour changes silently at each checkpoint
Policy is yours, not the vendor's

The row that matters most for a buying decision is the second one. Flat is bad, but unstable is worse, because unstable means you cannot even measure your own posture. If a benign edit to a prompt changes the security properties of the output, then any number you produce about your AI-generated code quality is a snapshot of a system that will be different tomorrow for reasons nobody logged.

What actually works: enforcement over instruction

Accept the two research results and the design follows almost mechanically. If instruction is neither reliable nor stable, then the control has to be a thing that acts, at the moment of action, and can refuse. In practice that is three components, and it is worth being precise about which one does what, because the temptation is to claim the first one does everything.

The agent-time layer: rules and findings reach the model in the prompt, and a hook evaluates the action before it runs.

Rules in context raise the floor. They do not set it. Putting your organisation's rules and the actual state of the repository into the model's context genuinely improves the first draft, and it puts your policy in front of whatever the repository happens to claim. But by the evidence above, context alone is a probabilistic improvement, not a guarantee. Anyone telling you otherwise is selling past the research.

Hooks are the part that is deterministic. A hook evaluates a tool call before it executes. Reading a credentials file, piping an environment dump to curl, running a destructive migration, invoking a tool whose description changed since yesterday: these are discrete, inspectable events, and a gate on them either fires or does not. It is not persuaded by a rephrased prompt. That is the whole reason it belongs in the design.

Findings in the loop remove the guessing. The agent has live access to what the scanners found across code, dependencies, secrets, infrastructure and pipelines, so a proposed change is reasoned against the repository's real state rather than against a prior. This is also what lets it notice second-order problems, like the fact that the pipeline it was just asked to edit runs on fork events with write permissions.

The honest summary of our own position: the first component makes the model behave better most of the time, the second makes a specific set of outcomes impossible, and the third makes both of them accurate. Only the second is a control in the strict sense. We would rather say that clearly than imply a prompt is a guarantee, because two papers now say it is not.

And the corollary for your roadmap: this problem does not get solved by waiting. Whatever the next release scores, plan on the security curve staying flat and the volume of code going up.

Frequently asked questions

Does a newer AI model write more secure code?

Barely, and not enough to change your controls. Functional correctness improves markedly across model generations while security pass rates stay close to flat. A newer model tends to handle the well-documented classes like SQL injection and weak cryptography better, because the safe pattern is also the common pattern in its training data, and it does not improve on classes that require knowing your runtime or your business rules. You get more code, at roughly the same defect rate.

Which model writes the most secure code?

Published comparisons do produce a ranking, and the ranking moves with every release, which is the reason not to build a security programme on it. The more useful reading of those studies is the aggregate: the spread between the best and the average model is much smaller than the gap between any model and "safe enough to ship unverified". Pick a model for capability and cost, then put a control in front of it.

Does telling the model to write secure code help?

Not measurably, on the evidence available. The May 2026 evaluation by Kharma and colleagues tested multiple prompting methods across five LLMs and four languages, including a chain-of-thought enriched with CWE mappings, and found no statistically significant reduction in vulnerability frequency or density. Prompting changed which CWE categories appeared, not how many vulnerabilities there were.

If prompting does not work, why do rules in the agent context matter at all?

Because they do two things a prompt-only theory undersells. They improve the first draft, which is a real efficiency gain even if it is probabilistic, and they put your organisation's policy in the model's context ahead of whatever an unreviewed repository file claims. What they cannot do is guarantee an outcome. That is why the hook exists alongside them, and why we do not present context as the whole answer.

Are the security benchmarks trustworthy?

The academic ones are careful and improving. CWEval covers 31 CWE types across five languages with outcome-driven evaluation, RealSec-bench is built from real high-risk Java repositories, and SecureAgentBench targets realistic vulnerability scenarios. Their limits are structural rather than methodological: they grade single-shot generation rather than long agent sessions, they can only test weaknesses that have a named class, and they say nothing about the agent's actions as opposed to its code.

Should we stay on an older model for safety reasons?

No. Older models are not more secure, they are just less capable, so you get the same defect rate with less output. The relevant frontier-model risks, an agent that executes a hostile plan competently, are addressed by constraining actions rather than by capping capability.

Does this mean AI-generated code cannot be shipped safely?

It can, on the condition that verification and enforcement are part of the loop rather than a stage after it. The failure mode is not "AI writes bad code", it is "AI writes code faster than the review that was supposed to check it". For the broader version of that argument, see AI coding agent security.

What single metric should we track instead of a model's security score?

Track the share of unsafe actions that were refused rather than reviewed. A pass rate tells you about a vendor's checkpoint. A refusal rate tells you about your own control, it is measurable in your logs, and unlike a benchmark score it does not reset when someone ships a new model.

Live · just shipped

Install VibeDefend in 5 seconds.

One command wires every coding agent on your machine to CybeDefend: your business rules, your compliance frameworks, and guards that block destructive calls before they fire.

Install in 5 secondsNode 18.17+
npx -y @cybedefend/vibedefend@latest install
Auto-detects
  • Claude CodeClaude Code
  • CursorCursor
  • OpenAI CodexOpenAI Codex
  • WindsurfWindsurf
  • GitHub CopilotVS Code Copilot
Read the README on npm