TL;DR
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.
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:
** CodeRabbit's December 2025 report** compared 470 real-world GitHub pull requests:
** Apiiro's research across Fortune 50 enterprises** found:
An earlier ** academic study analyzing GitHub Copilot output** found that
The pattern holds across every source: AI tools write functional code fast, but that code disproportionately fails basic security checks.
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.
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.
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.
MD5 for password hashing, ECB mode for encryption, static IVs. Syntactically correct, compiles clean, sits quietly broken in production.
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.
User input passed straight into os.system()
or subprocess.call()
without escaping.
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:
- 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:
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.
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.