[ THE_SHORT_ANSWER ]

Measured across published research rather than opinion, AI-generated applications fail in a consistent order. Broken access control dominates and is ranked first in the OWASP Top 10 for 2025, found in some form in 100% of applications tested. Then secrets shipped to the browser, then endpoints with no rate limiting or input validation, then injection and cross-site scripting, then dependencies that never existed. The pattern underneath all five: models are measurably better at making code work than at making it safe, and using one makes developers more confident, not less.

What the data actually says

Most writing about vibe coding security is a list of things that sound plausible. There is now enough published research to do better than that, so this article ranks the failures by measured frequency and attaches the study to each one.

Three findings frame everything below.

Working and safe are different bars, and the gap is enormous. Carnegie Mellon researchers found that 61% of AI-generated code functions correctly, while only 10.5% passes security review. The models clear the bar you can see.

Bigger models do not fix it. Veracode tested more than 100 language models and found 45% of generated code contained OWASP Top 10 vulnerabilities, with larger and newer models performing no better on security than smaller ones. That points at something systemic rather than a capability gap that scale will close. Security is not what these models are optimised against, because working code is what gets rewarded.

The tools make developers more confident, not more correct. Stanford researchers ran a controlled study and found participants with an AI assistant wrote less secure code than those without, and were more likely to believe their code was secure. That inversion is the reason these failures ship. Nobody overrode a warning. There was no warning.

One caveat applied throughout. The academic and OWASP figures below are solid. Some prevalence percentages come from companies that sell security scanners, and their methodology is not always published. I have labelled those as directional rather than presenting them as fact.

1. Broken access control

One customer can read another customer’s data. Not through any clever attack. By changing a number in a URL, or by signing up.

This is first by every available measure. OWASP ranks broken access control as A01 in its 2025 Top 10, and reports finding some form of it in 100% of applications tested. It is the most common serious flaw in software generally. Generated code is prone to it because access rules live outside the feature being generated.

It arrives in three distinct shapes, and they are worth separating because only one of them is obvious.

Missing rules. The database has no access policy at all. Anyone who finds your project can read everything. This is the version everyone knows about, and it is not hypothetical: CVE-2025-48757 covers a period during which the vibe coding platform Lovable generated Supabase databases without row-level security enabled, with more than 170 production applications confirmed exposed.

Permissive rules. The far more dangerous version, because it looks fine. The policy says, in effect, “allow this if the user is signed in.” It contains the word for authentication and passes a glance. It also means every person who creates an account can read every record you hold. Scanners covering these platforms track permissive policies as a separate category from missing ones, precisely because this kind survives review.

Object-level gaps. The API checks that you are logged in but never that the record belongs to you. Change the ID in the request and you get someone else’s invoice. Directional scan data puts this at the top of the frequency table for AI-generated CRUD endpoints, and it is the shape most likely to be present in an app that has otherwise been secured.

None of this indicts Firebase or Supabase, which are good products we use. The permissive default exists so you are not fighting your database on day one. It becomes a breach when nobody returns to close it, and nobody returns because the app works identically either way.

2. Secrets shipped to the browser

Your keys are in the JavaScript. Anything your app sends to a browser or packages into a phone app is readable, and people scan for this continuously and automatically.

Escape.tech scanned roughly 5,600 applications built on vibe coding platforms and found over 2,000 vulnerabilities, more than 400 exposed secrets including API keys, credentials and tokens, and 175 instances of exposed personal data covering medical records and bank details. That is a lower bound, since the testing ran in a deliberately conservative passive mode.

Two categories matter and they are not equal. Some keys are designed to be public and are safe on their own, provided the access rules behind them are correct, which loops directly back to failure one. Others are administrative keys that bypass every access rule you have configured. A single administrative key in a frontend bundle makes the rest of your security irrelevant.

The consequences split in two. There is the data breach, and there is the bill: a third-party key in a public bundle is a metered resource billed to you and usable by anyone who finds it. Compromised keys have been used to run up substantial charges on other people’s accounts overnight.

Checking this takes about a minute, which is what makes it frustrating. Open your app, open the browser’s network tab, and read what the client sends. A phone app is no better a hiding place, because anyone can unpack the package.

3. Endpoints nobody put a limit on

Someone can call your login page ten thousand times. Nothing stops them.

Rate limiting is invisible during development. You will never hit a limit you did not set, so nothing about building the app raises the question. Security firms scanning applications built on AI coding platforms report roughly four in five missing rate limiting on at least one authentication endpoint. Treat that figure as directional, but the direction is consistent across every published scan.

Missing input validation belongs in the same category and is described in these scans as close to universal. Generated request handlers accept what they are given: no length limits, no type checking, no restriction on what a field may contain.

These two group together because neither is a bug in the ordinary sense. Nothing is broken. A feature nobody requested is absent, and it happens to be the feature that stops your login page from serving as a free credential-testing service, and the one that stops the next failure on this list from being exploitable at all.

4. Injection and cross-site scripting

Text a user types gets treated as an instruction. A comment field that runs code in another user’s browser, or a search box that reaches the database as a command rather than as a search term.

This is the most rigorously measured item here, because it is easy to test at scale. Veracode’s study across more than 100 models found 86% of generated samples failed to defend against cross-site scripting and 88% failed against log injection. Georgetown’s CSET arrived at the same 86% figure for XSS independently.

It sits fourth rather than first for one reason: exploiting it usually requires reaching an endpoint, and endpoint exposure is covered above. But the failure rate is the highest of anything on this list, and unlike access control it rarely gets attention, because there is no configuration screen for it. Nobody forgot to switch it on. No one wrote the defence, and the code runs correctly without it.

5. Packages that never existed

Your app depends on software an AI invented. This is the newest failure on the list and the strangest.

Language models suggest software libraries that do not exist. Research presented at USENIX Security in 2025 examined 576,000 generated code samples across 16 models and found 19.7% of suggested packages were hallucinated. Newer frontier models have improved, with a 2026 follow-up measuring rates between roughly 4.6% and 6.1%, so this is getting better rather than worse.

The errors repeat, and that is what makes them dangerous. When researchers ran identical prompts ten times, 43% of hallucinated names appeared every single time and 58% appeared more than once. A consistently invented name is a predictable name, and an attacker can register it and wait. The industry calls this slopsquatting. Install it once and you have executed someone else’s code inside your build.

This ranks fifth because a few percent is a few percent, and it will keep falling. It earns its place because the consequence has no ceiling and because the check costs nothing: confirm that every dependency in your project is a real, maintained package with a history. Anything you have never heard of that appeared in a single generated file is worth thirty seconds of looking up.

Why this order, and what it means

Read the list from the top and a pattern emerges that has nothing to do with the models being bad at code.

Every failure here lives outside the thing being generated. Access rules sit in a different file from the feature they protect. Whether a key is safe depends on configuration elsewhere. Rate limiting is a property of a system, not a function. Input validation guards a boundary between two components. A dependency is somebody else’s software entirely.

Ask a model for a checkout screen and you get a good checkout screen. The code inside the file is usually fine, which is exactly what the Carnegie Mellon figure describes: 61% functions correctly. What no model does unprompted is walk back out, look at the whole system, and ask which of its assumptions are now wrong. That is the same distinction we traced through the hiring practices of the AI labs themselves, and it is why their interviews still test whether a person can reason about a system rather than produce a function.

That leads somewhere more useful than a warning about AI. All five of these are fixable, most of them in days rather than months, and none of them require throwing away what you built. They are configuration, boundaries and defaults: the layer that gets skipped when the thing already appears to work.

If you want the founder-facing version of this, the checks you can run yourself without an engineer, that is the five things I would check before production. And if you are wondering why an app that already works still costs something to own, that is free as in puppy.

[ NEXT STEP ]

Find out which of these five are in your app before someone else does.

A Flutter Codebase Rescue starts with an audit: we read what exists, test the access rules, the boundaries and the dependencies, and give you a prioritised list of what is actually exploitable rather than a scanner dump. Then we fix it in that order, without restarting the build from scratch.

SEE_CODEBASE_RESCUE →