Guide · 4 min read

The 10 most common security flaws in AI-generated code

AI assistants write code that works. Whether it’s secure, they only check when asked – and even then not reliably. These are the ten flaws we keep finding in AI-built apps.

How widespread the problem is shows in a large study by Veracode: more than 100 language models had to solve 80 coding tasks. In around 45% of cases the generated code contained a vulnerability from the OWASP Top 10. For Java the rate was above 70%, and against cross-site scripting the code was unprotected in 86% of cases (Veracode, July 2025).

That matches what we see in projects. The good news: most flaws follow a few recurring patterns.

1. Missing or overly open access rules

The most common and most dangerous flaw. The app checks whether someone is logged in – but not whether the requested data belongs to them. Replace /invoice/123 with /invoice/124 in the address and you see another customer’s invoice.

For apps on Supabase (typical for Lovable and Bolt) this means: row-level security isn’t enabled on some tables, or the policies allow too much. Then anyone who knows the public key from the browser can query the data directly. That was exactly the cause of CVE-2025-48757 in Lovable projects.

How to spot it: use two test accounts and try to access each other’s data. For Supabase we have a step-by-step guide.

2. Secret keys in the frontend or the repository

API keys for OpenAI, Stripe or the Supabase service role sit directly in code that is shipped to the browser – or in a .env file that ended up in the Git repository. Anything that reaches the browser is public. A service key there bypasses every access rule.

How to spot it: search the browser’s developer tools under “Sources” for sk_, service_role or secret. And check the repository history – a key committed once is still there after deletion and must be rotated.

3. Checks only in the browser

The AI builds a form that rejects invalid input and an “admin” button that only admins can see. The server checks neither. Anyone sending the request directly bypasses every rule.

Rule of thumb: every check that matters – permission, price, quantity, status – belongs on the server. In the browser it’s just convenience.

4. Injection: SQL, commands and prompts

Classic SQL injection has become rarer because modern libraries encourage parameterised queries. We still find it whenever the AI builds queries from text for a search or filter. New on the list is prompt injection: when user input flows unfiltered into an AI call that can use tools or data, an attacker can redirect the AI.

5. Cross-site scripting (XSS)

User content is rendered as HTML without checks – with dangerouslySetInnerHTML in React or v-html in Vue, often for “nicely formatted” text or Markdown. Injected code can then run in other users’ browsers and take over their sessions.

6. Home-made authentication

Instead of a proven service or established library, the AI builds its own login: passwords with a simple hash or even in plain text, session tokens in localStorage, no expiry, no protection against guessing. Each point is fixable – together they’re an open door.

7. Outdated and invented packages

AI models know the state of their training data. They suggest library versions with known vulnerabilities – and occasionally packages that don’t exist at all. Attackers deliberately register such invented names with malicious code.

How to spot it: run npm audit, pnpm audit or pip-audit, and look up every unfamiliar package on the registry before installing it.

8. No limits – neither for attackers nor for costs

Without rate limits a login can be guessed endlessly and a form abused as a spam cannon. AI features add a second risk: every request costs money. A bot calling your chat feature a thousand times ends up on your AI provider’s invoice.

9. Too much openness in production

Verbose error messages with stack traces in production, CORS: * for every origin, open admin or debug endpoints, default credentials as a “fallback” in code. Each point alone looks harmless; together they hand attackers the map.

10. No logging, no monitoring, no tested backup

Not a vulnerability in the narrow sense – but the reason a flaw turns into damage. Without logs nobody notices an attack. Without alerting a customer notices the outage first. And without a tested backup, data loss is final.

What now?

Three steps deliver the most security per hour of effort:

  1. Check access rules (point 1) – two test accounts, half an hour.
  2. Search for keys (point 2) – in the browser and the Git history; rotate everything you find.
  3. Audit dependencies (point 7) – one command, five minutes.

Everything else needs a look at the code. And there it often turns out that the security flaws are only the visible symptom – the cause usually lies in the architecture.