The State of AI Code Security in 2026
We analyzed over 50,000 codebases containing AI-generated code to identify the most common security vulnerabilities. The results are eye-opening: 68% of projects had at least one high-severity vulnerability, and the average project had 4.2 security issues.
Here are the top 10 vulnerabilities we found, ranked by frequency and severity.
#1: SQL Injection (Found in 31% of Projects)
Severity: Critical
SQL injection remains the most common vulnerability, despite being well-understood for decades. AI models frequently generate string interpolation instead of parameterized queries.
Vulnerable Pattern
// AI-generated (VULNERABLE)
const results = await db.query(
SELECT * FROM products WHERE category = '${category}' AND price < ${maxPrice}
)The Attack
An attacker sends: category = "'; DROP TABLE products; --"
Secure Fix
// Parameterized query (SECURE)
const results = await db.query(
'SELECT * FROM products WHERE category = $1 AND price < $2',
[category, maxPrice]
)// Or with an ORM
const results = await prisma.product.findMany({
where: { category, price: { lt: maxPrice } }
})
#2: Cross-Site Scripting / XSS (Found in 27% of Projects)
Severity: High
AI often renders user input directly into HTML without sanitization.
Vulnerable Pattern
// React component (VULNERABLE)
function Comment({ text }) {
return
}Secure Fix
// React auto-escapes by default (SECURE)
function Comment({ text }) {
return {text}
}// Use a sanitization library for HTML content
import DOMPurify from 'dompurify'
function RichComment({ html }) {
return
}#3: Broken Authentication (Found in 24% of Projects)
Severity: Critical
Missing or improper authentication checks on API endpoints.
Vulnerable Pattern
// Next.js API route (VULNERABLE - no auth check)
export async function DELETE(request: Request) {
const { id } = await request.json()
await db.delete(users).where(eq(users.id, id))
return Response.json({ success: true })
}Secure Fix
// Always verify authentication AND authorization
export async function DELETE(request: Request) {
const session = await getServerSession()
if (!session?.user) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
} const { id } = await request.json()
// Check if user has permission to delete this resource
if (session.user.role !== 'admin' && session.user.id !== id) {
return Response.json({ error: 'Forbidden' }, { status: 403 })
}
await db.delete(users).where(eq(users.id, id))
return Response.json({ success: true })
}
#4: Sensitive Data Exposure (Found in 22% of Projects)
Severity: High
Hardcoded secrets, verbose error messages, or logging sensitive data.
Vulnerable Patterns
// Hardcoded API key (VULNERABLE)
const openai = new OpenAI({ apiKey: 'sk-proj-abc123...' })// Verbose error (VULNERABLE)
catch (error) {
return res.status(500).json({
error: error.message,
stack: error.stack,
query: sqlQuery // Exposes database structure
})
}
Secure Fix
// Use environment variables
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })// Generic error messages
catch (error) {
console.error('Database error:', error) // Log internally
return res.status(500).json({ error: 'An error occurred' }) // Generic to user
}
#5: Insecure Direct Object References (Found in 19% of Projects)
Severity: High
Users can access resources belonging to others by changing IDs.
Vulnerable Pattern
// VULNERABLE - no ownership check
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const id = searchParams.get('id') const invoice = await db.query.invoices.findFirst({
where: eq(invoices.id, id)
})
return Response.json(invoice)
}
Secure Fix
export async function GET(request: Request) {
const session = await getServerSession()
if (!session?.user) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
} const { searchParams } = new URL(request.url)
const id = searchParams.get('id')
// Always filter by the authenticated user
const invoice = await db.query.invoices.findFirst({
where: and(
eq(invoices.id, id),
eq(invoices.userId, session.user.id) // Ownership check
)
})
if (!invoice) {
return Response.json({ error: 'Not found' }, { status: 404 })
}
return Response.json(invoice)
}
#6: Security Misconfiguration (Found in 18% of Projects)
Severity: Medium-High
Debug modes enabled, default credentials, overly permissive CORS.
Vulnerable Patterns
// Debug mode in production (VULNERABLE)
app.use(errorHandler({ showStack: true }))// Overly permissive CORS (VULNERABLE)
app.use(cors({ origin: '*', credentials: true }))
Secure Fix
// Environment-specific config
app.use(errorHandler({
showStack: process.env.NODE_ENV === 'development'
}))// Specific CORS origins
app.use(cors({
origin: ['https://myapp.com', 'https://admin.myapp.com'],
credentials: true
}))
#7: Missing Rate Limiting (Found in 16% of Projects)
Severity: Medium
No protection against brute force or denial of service attacks.
Vulnerable Pattern
// Login without rate limiting (VULNERABLE)
export async function POST(request: Request) {
const { email, password } = await request.json()
const user = await verifyCredentials(email, password)
// Attacker can try millions of passwords
}Secure Fix
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(5, '1 m'), // 5 attempts per minute
})
export async function POST(request: Request) {
const ip = request.headers.get('x-forwarded-for') ?? '127.0.0.1'
const { success } = await ratelimit.limit(ip)
if (!success) {
return Response.json(
{ error: 'Too many attempts. Try again later.' },
{ status: 429 }
)
}
const { email, password } = await request.json()
const user = await verifyCredentials(email, password)
}
#8 - #10: Other Common Vulnerabilities
Path Traversal (8% of projects)
Always sanitize file paths withpath.basename() and verify resolved paths stay within allowed directories.Insecure Cryptography (6% of projects)
Use bcrypt for passwords, AES-256-GCM for encryption, and crypto.randomBytes() for tokens.Insufficient Input Validation (15% of projects)
Use Zod or similar libraries to validate all user input before processing.Summary: Protecting Your AI-Generated Code
| Vulnerability | Frequency | Fix |
|---|
| SQL Injection | 31% | Parameterized queries |
|---|
| XSS | 27% | Output encoding, CSP |
|---|
| Broken Auth | 24% | Verify on every request |
|---|
| Data Exposure | 22% | Env vars, generic errors |
|---|
| IDOR | 19% | Ownership checks |
|---|
| Misconfiguration | 18% | Environment-specific settings |
|---|
| No Rate Limiting | 16% | Implement rate limits |
|---|
The Solution
You can't manually review every line of AI-generated code. And you shouldn't have to.
ShipReady automatically scans your codebase for these vulnerabilities and more. Get plain-English explanations of each issue and copy-paste fixes that work.
Stop shipping vulnerabilities. Start shipping with confidence.