The most common security vulnerabilities in AI-generated code
A reference guide to the eight vulnerability patterns AI coding tools (Cursor, Copilot, Claude, ChatGPT) introduce most often. Each entry includes a concrete example and the corrected version.
Short answer: Eight patterns account for the overwhelming majority of vulnerabilities AI coding tools introduce. They're listed below in order of how often we see them across scanned repos.
Each pattern has the same anatomy: the AI generates code that looks clean and runs correctly. The vulnerability is invisible at runtime — until an attacker probes it.
1. SQL injection via template literals
How often: The #1 finding across scanned repos. Appears in ~60% of AI-generated database code (Prev-ent internal data, 2026).
Example AI generates:
const q = `SELECT * FROM users WHERE email='${email}' AND pw='${pw}'`;
return db.query(q);Attack: Submit ' OR 1=1 -- in the email field. The query matches every row. Logged in as the first user (usually admin).
Fix:
const q = 'SELECT * FROM users WHERE email=$1 AND pw=$2';
return db.query(q, [email, pw]);2. Hardcoded API keys and secrets
How often: Found in ~35% of repos with AI-generated code. The most common leak vector for credentials in 2024 (GitGuardian, State of Secrets Sprawl 2024).
Example AI generates:
const stripe = new Stripe('sk_live_51H...');
const openai = new OpenAI({ apiKey: 'sk-proj-...' });Attack: Anyone with read access to the repo (or its git history, even after deletion) extracts the keys and uses them. With Stripe live keys: drain payments. With OpenAI keys: rack up bills on your account.
Fix: Move every secret to environment variables. Never commit .env. Rotate every key that has ever lived in source control.
3. Missing authorization checks
How often: Affects ~30% of AI-generated REST/Next.js routes.
Example AI generates:
export async function GET(req: Request) {
const userId = req.headers.get('x-user-id');
return Response.json(await db.user.findUnique({ where: { id: userId } }));
}Attack: The route trusts a header the user controls. An attacker passes any user's ID and reads their profile data. This is "Broken Access Control" — OWASP's #1 risk for 2021–2024.
Fix: Authenticate the request server-side. Use the session, not user-supplied headers.
4. Cross-site scripting via dangerouslySetInnerHTML
How often: Found in ~20% of AI-generated React components that render user content.
Example AI generates:
<div dangerouslySetInnerHTML={{ __html: comment.body }} />Attack: User posts a comment containing <img src=x onerror="fetch('/api/admin/users')">. When anyone views the page, the JavaScript runs in their browser, stealing their session.
Fix: Render text as {comment.body}. If you must render HTML, sanitize with DOMPurify first.
5. Path traversal
How often: ~15% of AI-generated file-serving endpoints.
Example AI generates:
const file = req.query.name;
return readFile(`./uploads/${file}`);Attack: Request ?name=../../etc/passwd and read arbitrary files on the server.
Fix: Resolve the path and verify it's still inside the intended directory:
import path from 'path';
const safe = path.resolve('./uploads', file);
if (!safe.startsWith(path.resolve('./uploads/'))) throw new Error('Bad path');6. Server-Side Request Forgery (SSRF)
How often: ~12% of AI-generated image proxies, link previewers, and webhook handlers.
Example AI generates:
const res = await fetch(req.query.url);
return new Response(await res.text());Attack: Request ?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ (AWS metadata endpoint) and the server happily fetches and returns cloud credentials.
Fix: Allow-list the hostnames you're willing to fetch. Block private IP ranges (10.x, 172.16–31.x, 192.168.x, 169.254.x, ::1, fc00::/7).
7. Insecure deserialization
How often: ~10% of AI-generated code that handles JSON or YAML from external sources.
Example AI generates (Python):
import pickle
config = pickle.loads(request.data)Attack: Pickle deserialization in Python (and equivalents in Ruby, Java) allows arbitrary code execution. An attacker crafts a payload that runs commands on your server during deserialization.
Fix: Never deserialize untrusted data with pickle, Marshal, or YAML's unsafe loaders. Use JSON for data from any external source.
8. JWT misuse (alg:none, hardcoded secrets, no expiration)
How often: ~8% of AI-generated auth implementations.
Three common variants:
- Accepting
alg: none: Some libraries default to accepting tokens with no signature. An attacker forges a token claiming to be any user. - Hardcoded signing secret: AI inlines a literal string like
'jwt-secret'. An attacker who reads the source can forge tokens. - No expiration: Tokens that never expire mean a leaked session is permanent.
Fix: Explicitly pin the algorithm (HS256 or RS256). Store the secret in env vars. Set expiresIn on every token. Reject tokens with alg: none.
How do I check for all eight in my own repo?
Connect your GitHub to Prev-ent. It scans your codebase, identifies any of these patterns, and shows you the exact attack scenario plus the corrected code. The first three scans are free. Most apps find at least one critical-severity issue on the first scan.
FAQ
What types of vulnerabilities does AI generate most often?
SQL injection via template literals, hardcoded API keys, missing authorization checks, cross-site scripting via dangerouslySetInnerHTML, path traversal, server-side request forgery, insecure deserialization, and JWT misuse are the top eight patterns seen across Cursor, Copilot, Claude, and ChatGPT output.
Why does AI keep introducing the same bugs?
Training data. AI models are trained on public code that prioritizes clarity over security. Tutorial code skips parameterization, example code inlines credentials, and StackOverflow answers ignore edge cases. The model reproduces these patterns confidently because they match what it saw most often.
Is one AI tool safer than another?
Marginally. As of 2025, Claude tends to ask about parameterization more often than Copilot; Cursor's default models vary by version. But all four mainstream tools (Cursor, Copilot, Claude, ChatGPT) introduce all eight patterns regularly. Tool choice is not a substitute for scanning.
Which vulnerability is the most dangerous?
SQL injection is the most exploitable — it gives an attacker full database access with no credentials. Hardcoded secrets are the most common and the easiest to exfiltrate at scale via leaked git history.
How do I fix SQL injection?
Use parameterized queries (placeholders like $1, ?, or :name) instead of template literals. The database engine treats parameters as data, never as code, so injection becomes impossible.
What is path traversal?
When a user-controlled value flows into a file path without sanitization, an attacker can request files outside the intended directory by including '..' in the path. Result: arbitrary file read on your server.
What is SSRF and why does it matter?
Server-Side Request Forgery. When your code fetches a URL the user controls, an attacker can point it at internal IPs (169.254.169.254 on cloud providers) to read metadata, internal APIs, or cloud credentials. AI commonly generates this when building proxies, image fetchers, and webhook handlers.
Scan your repo in 30 seconds.
Connect GitHub, pick a repo, see every vulnerability with the attack walkthrough and the fix. Free to start.
Scan a repo →