The AI-Generated Code Security Checklist: 12 Things to Verify Before You Merge
May 13, 2026 · 6-minute read · Seth
The AI-Generated Code Security Checklist: 12 Things to Verify Before You Merge
AI coding tools now write a meaningful share of the code shipping to production. GitHub reports Copilot is generating up to 46% of code in files where it's active. Cursor and Claude Code are accelerating the curve. The productivity gains are real.
The security gains are not. AI tools are extraordinary at synthesizing patterns from training data. They are mediocre at the things that actually keep production safe — authorization context, tenant isolation, dependency hygiene, and judgment about what not to include.
What follows is a checklist of the twelve security gaps we see most often in AI-generated pull requests. Each item is one specific failure mode, what causes the model to miss it, and how to verify before you merge.
Authorization & access
1. Authorization middleware missing on new endpoints
AI generates the route handler. It often forgets the auth middleware.
The pattern: a model is asked to "add an endpoint that returns user data." It produces a clean handler that fetches and returns the data. The route is registered. Auth is not enforced.
Why it happens: the prompt asked for the endpoint, not the security model around it. The model defaults to the happy path.
How to verify: grep for every new route registration. Confirm each one passes through your auth middleware before the handler runs. If your framework supports it, set a global auth-required default and require explicit opt-out.
2. Tenant isolation dropped from database queries
In multi-tenant systems, every query needs a WHERE tenant_id = ? or WHERE user_id = ? clause. AI-generated queries lose this constraint constantly when the model is focused on the business logic.
The pattern: a working query gets refactored into a function. The tenant filter quietly disappears in the refactor because the original context isn't carried forward.
How to verify: run a static check on every PR that searches for new database query patterns and flags any that don't reference the tenant identifier. If you don't have one, write one — it's 50 lines of code and it pays for itself within a month.
3. Mass assignment vulnerabilities in ORM updates
The pattern: a model writes User.update(request.body) or its equivalent. Whatever fields the attacker sends — is_admin, role, verified_email — get assigned.
Why it happens: AI tools optimize for terse, idiomatic code. Explicit field allow-lists feel verbose. They aren't.
How to verify: every update or create taking a request body should specify an explicit list of allowed fields. Never update(request.body). Never User(**data) on untrusted input.
Secrets & configuration
4. Credentials inlined in code
AI tools sometimes embed secrets they've seen in the conversation directly into code — API keys, connection strings, even passwords. This happens when a developer pastes a working configuration into chat to "fix it" and the model writes the fix with the secret baked in.
How to verify: run trufflehog or gitleaks on every PR. Block merges on detection. This is non-negotiable.
5. CORS misconfiguration on authenticated endpoints
The pattern: Access-Control-Allow-Origin: * set on endpoints that also accept credentials. AI suggests the permissive setting because it makes development friction go away.
How to verify: any endpoint that reads cookies or returns user-specific data must have an explicit origin allow-list. Wildcard origins should only ever appear on public, unauthenticated endpoints.
Input validation
6. Type validation present, range validation absent
AI generates schemas that validate email is a string but not email is under 254 characters. Or quantity is a number but not quantity is between 1 and 999. The absent bounds turn into DoS vectors and database overflows.
How to verify: every numeric field should have min and max constraints. Every string field should have a length cap. Use a validation library that requires these rather than allowing them to be optional.
7. Path traversal in file operations
The pattern: a function takes a filename and reads it from disk. The filename comes from user input. The code does not sanitize ../ segments.
How to verify: any file operation taking a user-controlled path needs explicit path resolution and a check that the resolved path stays inside the allowed directory. path.resolve() + a prefix check, every time.
8. SQL injection in string-concatenated queries
Modern ORMs make this rare, but AI-generated code that drops to raw SQL — for performance reasons or unusual queries — frequently reintroduces concatenated strings.
How to verify: every raw SQL execution should use parameterized queries. Grep your codebase for db.execute(f"..." or db.raw("SELECT" + patterns. There should be zero matches.
Dependencies & supply chain
9. Outdated or vulnerable package versions
AI tools were trained on snapshots of npm and PyPI from months ago. They will confidently suggest installing lodash@4.17.15 when you should be on the latest patched version. They will recommend libraries that have been deprecated.
How to verify: every PR that touches package.json or requirements.txt runs through npm audit, pip-audit, or Dependabot. Block on high-severity findings.
10. Typosquatted or hallucinated packages
AI tools sometimes hallucinate package names that don't exist — requests-http instead of requests, lodash-es-utils instead of lodash. Attackers register the hallucinated names with malicious payloads in advance. This is now an active attack pattern.
How to verify: any newly added dependency in a PR should be validated against an allowlist or have its publisher checked. Treat unfamiliar package names as suspicious until proven otherwise.
Data handling
11. PII or secrets leaked to logs
The pattern: an error handler catches an exception and logs the entire request body. Or a debug log statement prints the full user object including hashed passwords or auth tokens.
How to verify: all logging should use structured logs with explicit field allow-lists. Never console.log(request) or logger.info(user). Never log unredacted error objects in production. Run log scrubbing tools against staging output.
12. Missing CSRF protection on state-changing endpoints
Single-page apps and modern frameworks have made CSRF less common, but AI-generated code targeting older patterns (Flask, Express without middleware, Rails when CSRF is disabled) often skips CSRF tokens on POST/PUT/DELETE endpoints.
How to verify: any state-changing endpoint authenticated via cookie should require a CSRF token. APIs authenticated via bearer token in a header (and that don't accept cookies) are exempt — but verify they actually don't accept cookies, because frameworks sometimes accept both silently.
How long does this checklist take?
For a single AI-generated PR with one new endpoint and a handful of file changes, running the full checklist by a senior engineer takes 30 to 45 minutes. For an average company shipping 10-30 AI-generated PRs a week, that's three to twenty engineer-hours weekly that someone has to find.
Most teams don't find them. The PRs get cursory review and merge.
The shortcut
We built Fairy to make this stop being a bottleneck. Submit any AI-generated PR — we'll have a staff-level security engineer run this exact checklist and sign off in 24 hours for $1,000. If anything we sign off on causes a critical bug or vulnerability in production, we refund the review and help you fix it on us.
Submit a PR for verification →
This checklist is also available as a downloadable PDF. We add new entries quarterly as AI-coding patterns evolve. If you've caught a class of bug not on this list, we'd like to hear about it — we maintain a public registry of AI-generated vulnerability patterns.
Have AI-generated work you’d want verified? Connect with a Fairy →
More resources