TL;DR
- Nearly half of AI-generated code fails basic security tests — and that number hasn't budged as models got bigger.
- Java is the riskiest language, XSS is the vulnerability models handle worst, and it's not close.
- Three cheap layers (prompt, pre-commit, CI/CD) catch most of it. None take more than an afternoon to set up.
AI coding tools like Claude Code, Cursor, and Codex have changed how software gets written. But they've also introduced a class of risk most teams haven't caught up with yet.
You ask an AI coding agent to write a login handler. It produces working code in seconds — password hashing, database queries, error handling, all there. It looks clean. It passes your tests. You ship it.
There's a reasonable chance it also contains a flaw a static analysis tool would catch in five minutes.
This post covers what the data actually says, what goes wrong most often, and what you can do about it — whether you're a solo dev or a small team shipping fast.
What the Data Shows
The numbers aren't subtle.
Veracode's 2025 GenAI Code Security Report tested code generated by over 100 LLMs across Java, Python, C#, and JavaScript:
- 45% of AI-generated code samples failed security tests and introduced OWASP Top 10 vulnerabilities
- Java was the riskiest language tested, with a 72% security failure rate
- Cross-Site Scripting (CWE-80) was the single worst category, with models failing to defend against it in 86% of relevant tasks
- Bigger and newer models did not improve security. Scaling up model size didn't translate to safer output — pass rates for newer models like GPT-5 and Claude Sonnet 4.5 still cluster around the same 50–55% mark as their predecessors
CodeRabbit's December 2025 report compared 470 real-world GitHub pull requests:
- AI-co-authored PRs contained roughly 1.7× more issues overall than human-only PRs
- For XSS specifically, AI-generated code was 2.74× more likely to introduce the vulnerability
Apiiro's research across Fortune 50 enterprises found:
- 322% more privilege escalation paths in AI-assisted codebases
- 153% more design flaws
- 40% increase in secrets exposure
An earlier academic study analyzing GitHub Copilot output found that 29.6% of Copilot-generated snippets contained security weaknesses across 38 CWE categories.
The pattern holds across every source: AI tools write functional code fast, but that code disproportionately fails basic security checks.
Why Bigger Models Aren't Safer
More parameters and more training data don't make a model security-aware. LLMs learn patterns from the code they were trained on — and a meaningful chunk of public code is itself vulnerable. There's no internal "security reviewer" running in the background; the model is generating the statistically likely completion, not the correct one.
Ask it to write a database query, and it'll reach for whatever pattern shows up most in its training data. If that pattern is string concatenation instead of a parameterized query, you get confident, working, exploitable SQL injection — and nothing in the output will look wrong at a glance.
The Five Vulnerabilities AI Introduces Most Often
1. Hardcoded Secrets and API Keys
Placeholder credentials that look real — sample keys, connection strings with embedded passwords. Code works, tests pass, secret sits in plaintext for anyone with repo access.
2. SQL Injection via String Concatenation
AI defaults to f-strings or + concatenation for queries instead of parameterized statements. The fastest way to write a query is also the fastest way to create SQL injection.
3. Weak Cryptography
MD5 for password hashing, ECB mode for encryption, static IVs. Syntactically correct, compiles clean, sits quietly broken in production.
4. Missing Authorization Checks
Endpoints handle the request correctly but skip verifying the caller actually has permission to make it. Creates privilege escalation paths that normal functional testing won't surface.
5. Command Injection
User input passed straight into os.system() or subprocess.call() without escaping.
Three Layers of Protection
You don't need to stop using AI tools. You need checkpoints between "the model wrote this" and "this is in production."
Layer 1 — At the Prompt
Be explicit about security requirements instead of assuming the model will infer them:
"Write a parameterized SQL query to select users by email. Use prepared statements, not string formatting."
This alone measurably improves output — models default to secure patterns when told to, they just don't volunteer them.
Layer 2 — Before Commit
Add fast, local checks that run before code ever leaves your machine:
- Gitleaks — catches hardcoded secrets and keys
- Semgrep — SAST rules for injection, weak crypto, and more
- A pre-commit hook wiring both in
# example .pre-commit-config.yaml entries
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.4
hooks:
- id: gitleaks
- repo: https://github.com/returntocorp/semgrep
rev: v1.78.0
hooks:
- id: semgrep
args: ["--config=auto"]
Most teams have this running in under 30 minutes.
Layer 3 — In CI/CD
Catch what slips past local checks on every pull request:
- GitHub CodeQL for deeper static analysis
- Dependabot / Snyk for vulnerable dependencies
None of this is exotic tooling — it's the same stack most security-conscious teams already run. The difference is treating AI output as untrusted input by default, not as an exception case.
The Bottom Line
AI coding tools aren't going away, and they shouldn't. But the security cost is real, and it doesn't shrink as the models get bigger. The teams that benefit most treat AI output the way they'd treat a pull request from a junior developer: useful, fast, and unmerged until it's been reviewed.
If you're already running Semgrep or CodeQL, the marginal cost of pointing it at AI-generated code is close to zero. The cost of not doing it shows up later, in production, when it's a lot more expensive to fix.
Top comments (0)