Is Your AI-Written Code Secure? The Vibe-Coding Security Gap

Is Your AI-Written Code Secure? The Vibe-Coding Security Gap

Ankur Garg8 min read

Your engineers are shipping AI-written code today, whether or not you have a policy about it. The autocomplete suggests a function and they accept it. The agent scaffolds a feature, a Dockerfile, a Terraform module, and they wire it in. It works, the demo lands, the ticket closes. The question nobody stops to ask is whether that code was secure, and the reason the question does not get asked is that insecure code looks exactly like secure code until someone attacks it.

There is now real data on this, and it is worth more than the usual hand-waving. The security firm IOActive built a benchmark of 730 prompts spanning 216 vulnerability categories across 27 programming languages, ran it against 27 models and coding tools plus 125 configurations, and scored every output. It is the most serious empirical look at the question we have. The topline is bad enough: an average security score of 58.9%, with 31.6% of all generated samples fully vulnerable and only 52.6% fully secure. Roughly a third of AI-written code samples were not just imperfect, they were exploitable with no meaningful mitigation.

But the average is the least interesting number in the study, and treating it as the headline is exactly how these discussions stay shallow. The important finding is not that AI code is 59% secure on average. It is that the insecurity is not spread evenly. AI writes its safest code where it barely matters and its most dangerous code where it matters most. Understanding that distribution is the difference between a policy that works and a policy that makes you feel better.

The Average Is a Lie. Look at the Distribution.

When IOActive broke the results down by vulnerability category, the range was staggering: from 100% secure in some categories to 0% secure in others, a hundred-point spread. The model was essentially flawless at avoiding certain memory-safety bugs like double-free. And it was essentially incapable of producing secure code for others. Fourteen vulnerability categories scored under 30% secure, meaning the model failed to write safe code there at least seven times out of ten.

Now look at which categories fell where. The near-perfect scores clustered on low-frequency, esoteric issues. The catastrophic scores clustered on the primitives every real application depends on:

Where AI writes secure codeWhere AI fails
Memory safety (e.g. double-free): near 100% secureInsecure authentication: near 0% secure
Several low-frequency, exotic bug classesBroken access control, SQL injection, insecure cryptography: very high vulnerability rates
Container security: only 23.3% secure
CI/CD pipeline security: roughly 98% vulnerable

Read that table as a threat model. The single most security-critical component in almost any system is the code that decides who you are and what you are allowed to do. That is authentication and access control, and it is precisely where the models scored close to zero. AI is at its most confident and least competent exactly where a mistake is most expensive. It will happily generate a login flow that looks clean, reads well, and quietly accepts a forged token.

This is the finding that should change behavior. The problem is not a diffuse 40% chance of a bug somewhere. It is a concentrated, predictable failure on auth, access control, injection-prone data paths, and cryptography. You know in advance where the landmines are. That is actually good news, because it tells you exactly where to spend your scarce review attention.

The Most Dangerous Code Is the Code Nobody Reviews

Here is the finding that should genuinely worry a mid-market operator. IOActive found that infrastructure-as-code and cloud deployment code was 20.3 percentage points less secure than typical AI-generated application code (40.5% versus 60.8%). Container security sat at 23.3% secure. CI/CD pipeline configuration was roughly 98% vulnerable in their sample. Cloud datastore code was under half secure.

Sit with that, because it collides with how teams actually work. Application code gets reviewed. A pull request that changes the checkout logic gets eyes on it. But the Dockerfile, the Terraform module, the GitHub Actions workflow, the Kubernetes manifest, the IAM policy? That is "just config." It gets a glance and a rubber stamp, and increasingly it gets written wholesale by an agent that nobody double-checks because it is not "real code."

It is the most dangerous code in your stack. A single AI-generated line that makes a storage bucket public, grants an over-broad IAM role, opens a security group to the world, or bakes a secret into a container image does not cause a subtle bug. It causes a breach. The blast radius of bad infrastructure code is the entire environment, and it is exactly the layer where the models are worst and your review is thinnest. If you take one operational change from this article, it is this: your cloud and CI configuration needs more scrutiny than your application code, not less, and the opposite is almost certainly true in your shop today.

"Just Tell It to Be Secure" Is Not the Fix You Think It Is

The comforting response to all of this is: fine, we will just instruct the AI to write secure code. And there is real signal that prompting helps. The best configuration in the entire study, an agent equipped with a dedicated security skill, scored 83.8%, nearly 25 points above the average. Wrapping matters too: Claude Code's CLI scored 7.5 points higher than the raw model underneath it (63.4% versus 55.9%), which tells you the harness around a model is itself a security control, not just an ergonomics choice.

But the naive version of this advice, add a "be secure" line to your prompt, is wrong, and the data shows why. Security prompting is provider-dependent. Anthropic models improved 5.4 to 6.8 points when prompted for security. OpenAI models barely moved, 0.2 to 1.2 points. And most of the local open-weight models tested actually got worse when told to be secure, regressing by as much as 6.7 points. For four out of five Ollama models, security-aware prompting degraded their output.

The intervention that improves your setup can silently harm someone else's. There is no universal "secure mode" switch, only a knob you have to measure on your own stack.

This matters enormously if your team runs local or open models for cost or privacy reasons, which many mid-market teams increasingly do. You may be adding a security instruction that is making your code less safe, and you would never know, because insecure code still passes the demo. The optimal level of security prompting also varied model by model. There is no shortcut that survives contact with your actual toolchain. You have to test it.

No Model Is Safe, So Stop Trying to Pick One

The deepest implication of the study is easy to miss. Even the best configuration, at 83.8%, still produced 90 exploitable vulnerabilities out of 730 test cases. That is roughly one in eight. There is no model, no wrapper, and no prompt that gets you to "safe." The entire framing of "which AI writes the most secure code" is a distraction, because the answer for every one of them is "not secure enough to trust unverified."

That reframes the whole problem. If you cannot buy your way to safety by choosing the right model, then safety has to come from the system you build around whichever model you use. Snyk put the shift plainly: the risk is no longer confined to code after it is written. Agents pull in untrusted inputs, act with limited oversight, and generate output faster than any human review process was designed to catch. They name three exposures worth committing to memory: untrusted inputs, unbounded behavior, and unverified output. The volume is the real enemy. If AI multiplies the amount of code your team ships by five or ten, and your review capacity stays flat, the fully-vulnerable third does not stay a third of a small number. It compounds into structural security debt that post-hoc review can never catch up to.

What Actually Moves the Needle

The good news is that the same data that diagnoses the problem prescribes the fix. Not a vague "add controls," but specific, ordered moves that match where the risk actually is.

Tier your review by where the model fails, not by vibes. The UK's National Cyber Security Centre offers a useful frame they call the vibe-coding spectrum: match the level of AI autonomy to the stakes of the code. Their line is worth keeping: the risk is not in using AI, it is in not applying the right safeguards when the stakes are high. But the IOActive data sharpens it. Do not just tier by business importance in the abstract. Tier by the intersection of stakes and measured model weakness. Authentication, authorization, cryptography, injection-prone data handling, and every piece of infrastructure and CI config get mandatory human review plus automated scanning. Pure business logic and internal prototypes can run at full AI speed. You now know the list. Write it into your engineering standards.

Move security into the loop, and gate on the right things. Because volume beats human review, the check has to run as the code is written, not three sprints later in a pen test. That means static analysis, secret scanning, and, critically, infrastructure-as-code scanning wired into the pull request as a merge gate on the high-risk tiers. The IaC scanning is the piece most teams skip and the one this data says matters most. One caution born of experience: a scanner that floods agents and engineers with false positives gets ignored within a week. Tune for signal. A small set of high-confidence, blocking rules beats a thousand advisory warnings nobody reads.

Treat verification as the actual trust mechanism. Since no model is safe by default, trust has to be earned by checking, every time. The best public example is the engineer who used Claude Code to port 100,000 lines of TypeScript to Rust in a month. It worked at scale not because the agent was trusted but because it was relentlessly verified: deterministic test seeds scaled from 100 cases to 2.4 million, surfacing failures methodically until divergence dropped to 0.003%. He also documented the agent's constant instinct to cut corners, generating "simplified versions" and hardcoded workarounds rather than doing the real thing. That instinct is the source of insecure defaults, and verification is what catches it. Your equivalent is a real test suite plus security checks on every change, not faith in the output.

Use your stack as a lever. This one is rarely said out loud. The study found large differences in AI-generated vulnerability rates by language: Rust came out at 15.2% vulnerable versus 43.4% for Python and 31.2% for JavaScript, with Go also materially safer. A stricter, memory-safe language does not just help human authors, it constrains what an AI can get wrong. For a new security-critical service, the choice of language is a security decision with measurable payoff, not just a taste preference.

Standardize the harness, and know what the AI wrote. Since the wrapper around a model measurably changes its security output, your choice and configuration of coding tool is a control worth standardizing across the team, not leaving to individual preference. And because you cannot govern what you cannot see, tag or track which parts of your codebase are AI-generated so you can weight review and scanning toward them. Provenance is not bureaucracy here, it is targeting.

What to Do Monday

If your company writes software and uses AI to do it, and by now that is essentially every company, the starting sequence is concrete:

  • Write down two tiers. High-stakes: authentication, authorization, cryptography, anything handling personal or financial data, and all infrastructure and CI/CD config. Low-stakes: prototypes, internal tools, pure business logic. Assign full-speed AI to the second and mandatory human-plus-automated review to the first.
  • Turn on infrastructure-as-code scanning as a blocking merge gate. This is the highest-leverage single control given where the models fail, and most teams do not have it.
  • Bake security requirements into your team's shared AI instructions, then actually test whether it helps your model. If you run local or open-weight models, verify it is not making things worse.
  • Make verification non-optional on the high-stakes tier: real tests plus security checks on every change, no merge without them.
  • Name an owner. Someone accountable for "is our AI-assisted code secure." When everyone is an engineer, no one owns security unless you assign it.

None of this slows a good team down where speed matters. It slows them down precisely at authentication, access control, and the cloud config, which is exactly where slowing down is the point. The companies that get burned by AI-generated code will be the ones that read the 59% average, decided it sounded manageable, and shipped. The ones that pull ahead will be those who read the distribution, saw that the danger is concentrated and predictable, and put their scrutiny exactly there. The model is rarely the bottleneck, and choosing a different one will not save you. The discipline around it is the whole game.

Share
Ankur Garg

Author

Written by Ankur Garg. Ex-Great Learning and Capital One, with an IIM-Ahmedabad MBA and an IIT-Madras engineering degree. Has built AI products, sold them into enterprises, scaled EdTech from zero, and led P&L, regulatory and BFSI transformation. Advises mid-market and consumer-tech teams on AI strategy, process redesign, and the adoption work that makes AI actually pay off.

Ankur Garg on LinkedIn ↗

Want this for your team?

Book a free 30-minute AI opportunity assessment. You'll leave with at least one concrete idea.

Book a call

Discussion

Comments are coming soon.