Metamindz Logo

Why AI-Generated Code Keeps Failing on Authorisation

AI writes authentication well and authorisation badly. That gap, broken access control, is 2026's #1 web risk and the top way vibe-coded apps leak data. Here's why LLMs get it wrong, the breach data, and a five-step fix.
Why AI-Generated Code Keeps Failing on Authorisation

Why AI-Generated Code Keeps Failing on Authorisation

AI-generated code keeps failing on authorisation because a language model can write code that looks like it checks who you are, but almost never checks whether the thing you asked for is actually yours. That gap is called broken access control, and it is now the number one web security risk of 2026. It is also the single most common way vibe-coded apps get breached.

A broken padlock dissolving into a grid of code, illustrating broken access control in AI-generated code

So, look. I do vibe-code fixes for a living now. Not because I planned to, but because founders keep sending me apps that a model built for them over a weekend, and the same wound is open every single time. The login works. The signup works. Stripe fires. And then you change one number in the URL and you are staring at another customer's data.

This post is about why that happens, how bad it actually is according to the 2026 data, and what to actually do about it. No fear-mongering. Just the mechanism, the numbers, and the fix.

What broken access control actually is

Access control is the rule that says a user can only do what they are allowed to do, and only touch data that belongs to them. Broken access control is when that rule is missing, half-written, or checked in the wrong place. The OWASP Top 10 for 2025 ranks it as A01, the most serious application security risk, and notes that 100% of applications they tested had some form of it.

The flavour that keeps biting AI-generated apps has a name: BOLA, Broken Object Level Authorization. Older docs call it IDOR (Insecure Direct Object Reference). Same wound. Your API confirms you are logged in, then hands you whatever object ID you ask for without checking that the object belongs to you.

Here is the whole bug in one line. An endpoint like GET /api/invoices/1043 checks that you have a valid session, then returns invoice 1043. It never asks the only question that matters: "is invoice 1043 yours?" Change 1043 to 1044 and you are reading someone else's invoice. That is it. That is the breach that leaked millions of records this year.

Why LLMs are structurally bad at this

A model is brilliant at the shape of code and rubbish at the intent behind it. Authentication has an obvious shape, so it nails it. There is a login form, a password hash, a session token, a middleware check. It has seen a million examples. It reproduces them well.

Authorisation has no universal shape. Whether you are allowed to see invoice 1043 depends on YOUR business rules. Are you the owner? An admin? On the same team? Past your trial? A model cannot infer your ownership model from a prompt that says "build me an invoicing app", so it does the statistically likely thing, which is to write the fetch and skip the ownership check. Veracode's Spring 2026 GenAI code security update found only 55% of AI code-generation tasks produced secure code across all models and tasks. That means 45% shipped a known flaw, with access control and injection leading the list.

Two user data vaults connected by an arrow bypassing a barrier, illustrating broken object level authorisation

There is a nastier detail. The model often writes code that appears to check authorisation. It will add a comment like // verify user owns this resource and then not actually enforce it at runtime. This is why a scanner alone struggles. The pattern looks right. Only someone who understands the business logic can see that the enforcement is missing. That is the difference between a tool that flags syntax and a human who understands what the app is supposed to do.

How bad is it? The 2026 numbers

This is not a hypothetical. The data from the first half of 2026 is genuinely grim, and it is consistent across independent sources.

Security firm Escape.tech scanned 5,600 publicly deployed vibe-coded applications and found over 2,000 high-impact vulnerabilities, more than 400 exposed secrets, and 175 instances of exposed personal data, including medical records and bank account numbers. Every one of those was live in production, discoverable within hours. BOLA was the most prevalent access control flaw in the set.

A separate Q1 2026 assessment found that 91.5% of vibe-coded apps contained at least one vulnerability traceable to AI hallucination. And CodeRabbit's analysis put AI-generated code at a 2.74x higher vulnerability rate than human-written code. Not slightly worse. Nearly three times worse.

Then there is the cost. IBM's Cost of a Data Breach report puts the global average breach at $4.44M and the US average at $10.22M. Most relevant here: 97% of AI-related breaches involved organisations that lacked proper access controls, and shadow AI added roughly $670,000 to the average breach. The pattern is not subtle.

SignalWhat the 2026 data showsSource
Broken access control rank#1 risk in OWASP Top 10 2025; found in 100% of tested appsOWASP
AI code that is secureOnly 55% of tasks; 45% ship a known flawVeracode Spring 2026
AI vs human vulnerability rate2.74x higher in AI-generated codeCodeRabbit
Vibe-coded apps with a vulnerability91.5%Q1 2026 assessment
Live vibe-coded apps scanned2,000+ vulns, 400+ secrets, 175 PII exposures across 5,600 appsEscape.tech
AI-related breaches lacking access controls97%IBM

The breaches this actually caused

Numbers get abstract, so here are three that happened.

Lovable. A researcher reported an IDOR flaw. It sat unactioned for 48 days, during which any free account holder could reach another user's source code, database credentials, and AI chat logs. Forty-eight days of open drawer.

Moltbook. Per Veracode's writeup, it leaked 1.5 million authentication tokens and 35,000 email addresses because API endpoints returned sensitive data without checking authorisation. The classic BOLA shape at scale.

The Tea app. 72,000 user images and 1.1 million private messages exposed through the same missing access controls. Real people, real photos, real messages, one missing ownership check.

None of these were exotic. No zero-day, no sophisticated attacker. Someone changed an ID and the server said "sure, here you go".

Agents are quietly making it worse

If you have moved from "AI writes a function" to "AI agent does the task", the authorisation surface gets larger, not smaller. Recent research on agent frameworks found something worth knowing: across LangChain/LangGraph, LlamaIndex, and the Stripe Agent Toolkit, none provides a deterministic, fail-closed, per-call authorisation gate by default. The frameworks conflate "the agent has access to this tool" with "the agent is authorised to use it on this specific value". Those are not the same thing. That is the confused-deputy problem, and it means your agent can read untrusted input and then call a payment or email tool it should never have used in that context.

The takeaway is boring but important. Giving a model a tool is not the same as authorising each individual action that tool can take. If you are wiring agents into payments, CRM, or infrastructure, the per-call authorisation check is on you, because the framework will not do it for you.

How to actually audit and fix it

A reinforced gate with a shield checkmark surrounding protected data blocks, illustrating an authorisation audit and fix

Good news: this is fixable, and it does not require a security PhD. Here is what I actually do when a founder hands me an app that a model built.

1. Enumerate every endpoint that takes an ID. Anything with a /:id, a query param, or an object reference in the body. That list is your risk surface. In a typical vibe-coded app it is longer than the founder expects, because the model generated CRUD routes for every table.

2. For each one, ask the ownership question out loud. "If I am user A and I request this with user B's ID, what happens?" If the answer is anything other than a 403 or 404, you have a BOLA. Test it manually. Two accounts, swap the IDs, watch what comes back. This finds more real bugs in an afternoon than most automated scans.

3. Push the check down to the database, not up in the controller. The most durable fix is to enforce ownership at the data layer, so a missing check in one route cannot leak everything. If you are on Postgres or Supabase, that means Row Level Security switched on for every tenant-scoped table. RLS being off by default is the root cause behind a lot of this year's breaches.

4. Make authorisation a single, boring, central function. Not scattered if statements the model sprinkled through 40 files. One can(user, action, resource) gate that every request goes through, and it fails closed. If the gate is not sure, it says no.

5. Add an authenticated scanner AND a human pass. Tools like Escape, Invicti, or Snyk will catch the obvious ones. But because AI writes code that looks authorised, you need someone who understands the business logic to read the routes that matter. The scanner and the human catch different bugs. You want both.

This is the exact work behind our Vibe-Code Fixes service, and it is why I am blunt with founders about the difference between a scanner subscription and an actual fix. A scanner tells you the drawer is open. It does not close it, and it certainly does not rewrite your authorisation model so it stays shut.

The typical approach vs a CTO-led fix

AspectTypical approachCTO-led approach (Metamindz)
Finding the bugRun a scanner, get a PDF of flagsScanner plus manual ID-swap testing across real accounts and business logic
Understanding itFounder left to interpret CVSS scores aloneWe explain exactly which data was reachable and by whom, in plain English
The fixPatch the flagged routes one by oneMove enforcement to the data layer (RLS), centralise the authorisation gate, fail closed
Agents and toolsAssume the framework handles authorisationPer-call authorisation gates on payment, email, and infra actions
After the fixSame team ships the next BOLA next weekGuardrails and review process so the model can't reintroduce it
HonestySold a retainer regardlessWe'll tell you if a one-off audit is all you need and point you there

To be fair to the models: none of this means "stop using AI to build". I use Claude Code and Cursor every day and ship faster because of them. The point is that authorisation is the one domain where you cannot trust the output by default. Treat AI-generated access control as guilty until proven innocent, and you avoid being the next entry on the breach list. This is the whole thesis behind structured AI adoption: AI as a productivity multiplier with human oversight where it counts, not vibe coding straight to production.

If you are raising, this matters twice over. A missing ownership check is one of the fastest ways to fail a technical due diligence. Investors' reviewers test for exactly this, and finding a live BOLA in your API is the kind of thing that knocks a valuation or kills a deal. Better to find it yourself first.

Frequently Asked Questions

Why does AI-generated code fail on authorisation specifically?

Because authorisation depends on your unique business rules, which a model cannot infer from a short prompt. It reliably writes authentication (a known, universal pattern) but skips the ownership check that decides whether a given record actually belongs to the requesting user. That gap is broken access control.

What is BOLA and how is it different from IDOR?

They are effectively the same flaw with different names. BOLA (Broken Object Level Authorization) is the current OWASP term; IDOR (Insecure Direct Object Reference) is the older one. In both, an API confirms you are logged in but hands over any object you request without checking that you own it.

How much AI-generated code actually has security flaws?

Veracode's Spring 2026 research found only 55% of AI code-generation tasks produced secure code, so 45% shipped a known flaw. CodeRabbit measured AI-generated code at 2.74x the vulnerability rate of human code, and one Q1 2026 study found 91.5% of vibe-coded apps had at least one vulnerability.

Can a security scanner find broken access control on its own?

Partly. Scanners catch obvious cases, but BOLA often needs business-logic understanding because AI writes code that looks authorised without enforcing it. The reliable method combines an authenticated scanner with manual testing (swapping IDs between two real accounts) and a human review of sensitive routes.

How do I fix broken access control in a vibe-coded app?

Enumerate every endpoint that takes an ID, test each with a second user's ID, push ownership checks down to the database (Row Level Security on Postgres or Supabase), centralise authorisation into one fail-closed function, and add per-call checks around any agent tools that touch payments or infrastructure.

So, if you have shipped something an AI built and you have never once changed a number in your own URL to see what comes back, do that today. If the wrong data shows up, that is your open drawer. Book a free CTO call and we'll close it properly, or tell you honestly if it's already fine. Either way you'll sleep better tonight.

This post touches on data breaches and security incidents. If your app is currently exposing user data, treat it as urgent, take the affected endpoints offline if you can, and get eyes on it fast.