The Problem
You ask AI to generate Python code. It works. You ask for JavaScript. Also works. But the Python code has pickle deserialization vulnerabilities, and the JavaScript has prototype pollution issues. Same AI, different language-specific security holes.
The core issue: Security vulnerabilities are language-specific, but AI training isn't.
AI learns patterns across languages but doesn't deeply understand each language's unique security pitfalls. Python's dynamic typing creates different risks than Go's static typing. JavaScript's prototypes enable attacks impossible in Rust.
The Core Insight
Know your language's Top 5 vulnerabilities and search for them first.
Every language has its "usual suspects" - the vulnerabilities that show up repeatedly. Once you know them, you can scan AI output in 60 seconds and catch 80% of issues.
Think of it like code smells, but for security. Each language has patterns that scream "vulnerable."
Python: The Top 5 AI Vulnerabilities
1. Unsafe Deserialization (pickle)
Why AI does this: pickle is common in Python tutorials. AI copies the pattern.
# Bad: AI loves to generate this
import pickle
def load_data(filename):
with open(filename, 'rb') as f:
return pickle.load(f) # Arbitrary code execution!
# Attacker can craft malicious pickle to run commands
# Good: Use safe serialization
import json
def load_data(filename):
with open(filename, 'r') as f:
return json.load(f)
Fix: Replace pickle with json, yaml.safe_load(), or msgpack.
2. SQL Injection via f-strings
Why AI does this: f-strings are idiomatic Python. AI uses them everywhere.
# Bad: f-string SQL injection
user_id = request.args.get('id')
query = f"SELECT * FROM users WHERE id = {user_id}"
cursor.execute(query)
# Attacker sends: id=1 OR 1=1
# Good: Parameterized queries
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))
3. Command Injection (os.system, subprocess.call)
Why AI does this: Shortest code path for shell commands.
# Bad: Direct command execution
import os
filename = request.form['filename']
os.system(f"cat {filename}") # Command injection!
# Attacker sends: file.txt; rm -rf /
# Good: Use subprocess with list args
import subprocess
subprocess.run(['cat', filename], check=True, capture_output=True)
4. Path Traversal
Why AI does this: Trusts user input for file paths.
# Bad: Direct file access
file_path = request.args.get('file')
with open(f'/uploads/{file_path}', 'r') as f:
return f.read()
# Attacker sends: file=../../etc/passwd
# Good: Validate and sanitize
import os
from pathlib import Path
UPLOAD_DIR = '/uploads'
file_path = request.args.get('file')
safe_path = (Path(UPLOAD_DIR) / file_path).resolve()
if not str(safe_path).startswith(UPLOAD_DIR):
raise ValueError("Invalid file path")
with open(safe_path, 'r') as f:
return f.read()
5. Timing Attacks in Authentication
Why AI does this: Uses standard equality checks.
# Bad: Early return leaks timing
def check_token(provided, expected):
if provided == expected: # Short-circuits on first mismatch
return True
return False
# Good: Constant-time comparison
import hmac
def check_token(provided, expected):
return hmac.compare_digest(provided, expected)
Python-Specific Scan
Search codebase for: pickle.load, eval(, exec(, os.system(, f"SELECT, == (in auth code)
JavaScript/Node.js: The Top 5 AI Vulnerabilities
1. Prototype Pollution
Why AI does this: Dynamic object manipulation is common in JS.
// Bad: User can pollute Object prototype
function merge(target, source) {
for (let key in source) {
target[key] = source[key];
}
}
// Attacker sends: {"__proto__": {"isAdmin": true}}
// Good: Use Object.assign with safe guards
function merge(target, source) {
const safeKeys = Object.keys(source).filter(
key => !['__proto__', 'constructor', 'prototype'].includes(key)
);
for (let key of safeKeys) {
target[key] = source[key];
}
}
2. ReDoS (Regular Expression Denial of Service)
Why AI does this: Generates complex regex without considering performance.
// Bad: Catastrophic backtracking
const emailRegex = /^([a-zA-Z0-9_\.\-])+@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
// Attacker sends: "aaaaaaaaaaaaaaaaaaaaaaaaaaaa!"
// Causes exponential regex execution time
// Good: Simpler regex or dedicated library
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// Or use: npm install email-validator
3. XSS via innerHTML
Why AI does this: Shortest code for DOM manipulation.
// Bad: Direct HTML injection
element.innerHTML = userInput;
// Attacker sends:
// Good: Use textContent or sanitize
element.textContent = userInput;
// If HTML needed:
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);
4. JWT Secret Hardcoding
Why AI does this: Examples use hardcoded secrets for simplicity.
// Bad: Hardcoded secret
const token = jwt.sign({ userId }, 'secret123');
// Good: Environment variable
const token = jwt.sign({ userId }, process.env.JWT_SECRET, {
expiresIn: '24h'
});
5. NoSQL Injection (MongoDB)
Why AI does this: Direct object queries seem safe but aren't.
// Bad: Direct query object
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = await User.findOne({ username, password });
// Attacker sends: {"username": {"$ne": null}, "password": {"$ne": null}}
});
// Good: Explicit validation
app.post('/login', async (req, res) => {
const { username, password } = req.body;
// Ensure strings, not objects
if (typeof username !== 'string' || typeof password !== 'string') {
return res.status(400).json({ error: 'Invalid input' });
}
const user = await User.findOne({ username });
const valid = await bcrypt.compare(password, user.passwordHash);
// ... rest of auth
});
Go: The Top 5 AI Vulnerabilities
1. SQL Injection in Query Building
// Bad: String concatenation
query := "SELECT * FROM users WHERE name = '" + userName + "'"
db.Exec(query)
// Good: Prepared statements
query := "SELECT * FROM users WHERE name = $1"
db.Query(query, userName)
2. Race Conditions (Concurrent Map Access)
Why AI does this: Generates concurrent code without sync primitives.
// Bad: Unsynchronized map writes
var cache = make(map[string]int)
go func() {
cache["key"] = 1 // Race condition!
}()
go func() {
cache["key"] = 2 // Race condition!
}()
// Good: Use sync.Map or mutex
import "sync"
var (
cache = make(map[string]int)
mu sync.RWMutex
)
go func() {
mu.Lock()
cache["key"] = 1
mu.Unlock()
}()
3. Path Traversal in filepath.Join
// Bad: filepath.Join doesn't prevent traversal
file := filepath.Join("/uploads", userPath) // Can escape with ../
// Good: Validate result
file := filepath.Join("/uploads", userPath)
if !strings.HasPrefix(file, "/uploads") {
return errors.New("invalid path")
}
4. Unbounded Goroutines
Why AI does this: Loves spawning goroutines without limits.
// Bad: Spawn goroutine per request
for _, item := range items {
go processItem(item) // Unbounded concurrency
}
// Good: Worker pool
semaphore := make(chan struct{}, 10) // Max 10 concurrent
for _, item := range items {
semaphore <- struct{}{}
go func(item Item) {
defer func() { <-semaphore }()
processItem(item)
}(item)
}
5. Unsafe Type Assertions
// Bad: Panic on wrong type
value := data.(string)
// Good: Check assertion
value, ok := data.(string)
if !ok {
return errors.New("invalid type")
}
Rust: The Top 3 AI Vulnerabilities
Note: Rust's compiler catches many vulnerabilities, but AI can still introduce logic errors.
1. Unsafe Blocks (use-after-free, buffer overrun)
// Bad: AI adds unsafe when it doesn't know the safe way
unsafe {
let data = *raw_ptr; // Could be freed already
}
// Good: Avoid unsafe unless absolutely necessary
// Use safe abstractions instead
2. Integer Overflow in Release Mode
// Bad: Silent overflow in release builds
let result = a + b; // Overflows silently
// Good: Checked arithmetic
let result = a.checked_add(b).ok_or("overflow")?;
3. Denial of Service via Unbounded Resources
// Bad: Read entire file into memory
let contents = fs::read_to_string(user_file)?;
// Good: Stream large files
use std::io::{BufRead, BufReader};
let file = File::open(user_file)?;
let reader = BufReader::new(file);
for line in reader.lines().take(1000) { // Limit lines
// Process line
}
Quick Reference
Language-Specific Security Scans:
Python: Search for:
pickle.load,eval(,exec(→ Arbitrary code executionf"SELECT,f"INSERT→ SQL injectionos.system(,subprocess.call(→ Command injection
JavaScript/Node: Search for:
innerHTML,eval(→ XSS__proto__in object merge → Prototype pollution- Complex regex on user input → ReDoS
Go: Search for:
"SELECT * FROM " +→ SQL injection- Map access in goroutines without sync → Race conditions
filepath.Joinwith user input → Path traversal
Language-Specific AI Prompts:
# Python
"Review for pickle deserialization, SQL injection via f-strings, and command injection"
# JavaScript
"Check for prototype pollution, XSS via innerHTML, and ReDoS in regex"
# Go
"Look for race conditions, SQL injection, and unbounded goroutines"