The security holes AI leaves in your code (and how to find them)

Here’s the uncomfortable finding that should shape how you think about AI-built software: when Veracode tested more than 100 large language models across 80 coding tasks, roughly 45% of the AI-generated code introduced an OWASP Top 10 vulnerability when no security guidance was given. That rate hasn’t meaningfully improved as models have grown larger and more capable.

This isn’t a reason to stop using AI tools. It’s a reason to understand exactly what they leave behind — because the flaws are remarkably consistent, and once you know the pattern, you can check for them.

Why AI code is insecure by default

AI coding tools are trained to produce code that works. Security is invisible to that objective: a login flow with hardcoded credentials looks identical, from the outside, to one with proper session handling. Both let you log in. Only one survives contact with someone who’s actually trying.

Compounding this, prompts almost never mention security. When you ask for “a user login,” you get a user login — not rate limiting, not session expiry, not protection against credential stuffing. The model gives you what you asked for. What you didn’t know to ask for simply doesn’t appear.

The five that show up every time

1. Secrets in the frontend. API keys, database connection strings, and third-party tokens hardcoded into client-side code or committed straight to the repo. This is the most common and most expensive mistake in AI-built apps — anyone can open dev tools and read them.

2. Authorization that isn’t there. The app checks who you are (authentication) but never checks what you’re allowed to see (authorization). The tell: you can change an ID in the URL and load someone else’s record. AI generates this flaw constantly because the happy-path demo never exercises it.

3. Unvalidated input. Every field a user touches is an attack surface. AI-generated code tends to trust input and pass it straight through — opening the door to injection attacks, cross-site scripting, and quietly corrupted data.

4. No rate limiting. Nothing stops one bot, scraper, or bad actor from hammering your endpoints — running up your bill, exhausting your database, or taking the service down for everyone else.

5. Leaky error handling. Unhandled errors that dump stack traces, internal paths, or database details straight to the user. Convenient in development, a roadmap for an attacker in production.

How to actually check

You don’t need to guess. Three concrete steps:

  • Search your codebase for secrets. Grep for api_key, password, secret, and token. If any real values live in the code or in git history, that’s finding number one — and rotating those keys is urgent, because git history is forever.
  • Try to break your own authorization. Log in as one user, then change record IDs in the URL and see what loads. If you can reach data that isn’t yours, so can anyone else.
  • Run the full checklist. Security is four of the twelve items on our production readiness checklist — the other eight (tests, performance, observability, deploys) matter too, but the security four are the ones that turn a bad day into a breach.

The honest bottom line

Building fast with AI and shipping securely aren’t in conflict — but they’re not the same activity, and the tools only do the first one. The apps that get burned aren’t the ones built with AI. They’re the ones where nobody went back and checked.

If you want to know where you actually stand, that’s precisely the work we do — an honest read of what’s solid, what’s exposed, and what it takes to close the gap.