AI models are trained to write code that works, not code that is secure — and the difference between those two goals produces a predictable set of security vulnerabilities that you must learn to catch in review.
Why AI-Generated Code Has Systematic Security Gaps
AI code generation is optimized to produce syntactically correct, functionally plausible code that satisfies the immediate request. Security properties, by contrast, require understanding threat models, trusting no input, and writing code that is defensive about things that have not happened yet. These are not properties that emerge naturally from predicting the most statistically likely next token.
In practice, AI assistants tend to produce code that:
- Handles the happy path correctly but is naive about adversarial input
- Trusts data from external sources (databases, APIs, user input) without validation
- Uses convenient but insecure defaults (SQL string interpolation, MD5 for password hashing, HTTP instead of HTTPS)
- Omits authorization checks in code that handles sensitive resources
- Generates complete examples that include hard-coded credentials for "clarity"
None of this is malicious. The model is pattern-matching on the billions of code examples it was trained on, many of which were tutorial code, examples written for readability, or legacy code with the security issues of their era. Recognizing these systematic patterns is what allows you to review AI-generated code efficiently.
Learning tip: Keep the OWASP Top 10 list open in a browser tab whenever you are reviewing AI-generated code. Cross-reference each new function or module against the list before approving it. This turns a vague concern ("is this secure?") into a structured checklist.
OWASP Top 10 Patterns That AI Commonly Introduces
A01: Broken Access Control. AI assistants frequently write CRUD endpoints without including authorization checks. A generated GET /api/users/:id handler may correctly fetch the user by ID but never verify that the requesting user is authorized to see that record. Always look for missing ownership checks, missing role-based access checks, and direct object reference patterns.
A03: Injection (SQL, Command, LDAP). AI will often generate query code using string interpolation or concatenation, especially in response to quick prompts. Even when the developer specifies "write a database query," the generated code may use f-strings or template literals rather than parameterized queries if the example data in the prompt suggests that approach.
A04: Insecure Design. AI-generated authentication flows sometimes have structural flaws — for example, generating a password reset flow that sends a token in a URL query parameter that will end up in server logs, or a session management approach that uses predictable IDs.
A05: Security Misconfiguration. Generated configuration files, Docker setups, and cloud infrastructure code frequently use insecure defaults: CORS: *, debug: true in production configs, open security group rules in Terraform, overly permissive IAM policies.
A07: Identification and Authentication Failures. AI-generated authentication code may store passwords in plain text (especially in beginner-oriented examples), use weak hashing algorithms like MD5 or SHA1, fail to implement rate limiting on login endpoints, or generate JWT implementations that skip signature verification.
A08: Software and Data Integrity Failures. When generating deserialization code, file upload handlers, or code that processes external data formats, AI may omit type validation, size limits, or content-type verification.
A10: Server-Side Request Forgery (SSRF). Generated code that makes outbound HTTP requests based on user-provided URLs often does not validate or restrict the URL before making the request, enabling SSRF attacks.
Learning tip: When you receive AI-generated code, mentally label each function with the OWASP categories it could violate. A function that touches user input + a database = check for A03. A function that handles auth = check for A07. This targeted mental model is faster than a general "security review."
How to Write Security-Focused Review Prompts
The AI that generated vulnerable code can also identify the vulnerabilities in that code — if you ask it to. The key is framing the review request as an adversarial exercise rather than a general quality check.
Unfocused review prompt (less effective):
Is this code secure?
This produces generic, surface-level feedback.
Focused adversarial review prompt (more effective):
You are a security engineer performing a penetration-tester-style code review. Review the following code for:
1. SQL injection (check every database query for string interpolation)
2. Missing authorization checks (check every endpoint for ownership/role verification)
3. Insecure defaults (check config values, CORS settings, debug flags)
4. Hard-coded secrets or credentials
5. Missing input validation on user-supplied data
For each issue found, provide: the exact line or code block, the vulnerability type (OWASP category), the attack scenario, and a corrected version of the code.
[PASTE CODE HERE]
This prompt constrains the model to produce structured, actionable findings rather than vague reassurances.
Red team prompt for a specific attack scenario:
Assume you are an attacker who has access to the public API described by this code. Describe the three most exploitable vulnerabilities you would attempt to use, in order of severity. For each, explain: what input you would send, what you would expect to happen, and what data or access you could gain. Do not suggest fixes — just describe the attack.
[PASTE CODE HERE]
This adversarial framing forces the model out of "helpful assistant" mode and into a more honest evaluation of the code's weaknesses.
Learning tip: Never ask "is this code secure?" — ask "how would an attacker exploit this code?" The second question is harder to answer with reassuring non-answers and produces far more useful findings.
Specific Code Patterns to Always Check
Beyond the OWASP categories, there are specific structural patterns in AI-generated code that warrant automatic review attention:
User input handling. Any code path that takes data from an HTTP request, a form field, a URL parameter, a file upload, or a WebSocket message and uses it in a downstream operation. The question is: has this input been validated, sanitized, and type-checked before it touches a database, file system, shell command, or external API?
Authorization decisions. Find every place the code makes a decision about what a user can see, modify, or do. Check that the authorization decision is based on the authenticated user's identity and permissions, not on a user-supplied parameter that an attacker could modify.
File operations. Any code that reads or writes files using user-supplied path components. Check for path traversal vulnerabilities (../ sequences, absolute path injection). Check that file uploads have content-type validation, size limits, and are stored outside the web root.
External API calls. Any outbound HTTP request that uses a URL derived from user input. Check for SSRF. Check that the response is validated before being used. Check that the credentials for the external service are properly managed and not in the code.
Cryptographic operations. Any code that hashes, encrypts, or generates tokens. Verify: bcrypt/Argon2 for passwords (not MD5/SHA1), CSPRNG for token generation (not Math.random()), correct use of authenticated encryption (AES-GCM, not AES-ECB), valid certificate verification in TLS connections.
Learning tip: Build a personal "always check" annotation habit. When you start reviewing a file, add inline comments marking the four patterns above before you begin the detailed review. These annotations help you stay focused and serve as a record of what you examined.
Building a Security Checklist for AI-Generated Code
A repeatable checklist turns security review from an inconsistent art into a consistent process.
Checklist skeleton (adapt to your stack):
- Input validation: Are all user inputs validated for type, length, and format before use?
- SQL queries: Are all database queries using parameterized statements or an ORM with parameterized support?
- Authorization: Does every resource endpoint check that the requesting user owns or has permission for the resource?
- Authentication: Are passwords hashed with bcrypt or Argon2? Are tokens generated with a CSPRNG? Are session IDs sufficiently random?
- Secrets: Are there any hard-coded credentials, API keys, or connection strings in the code?
- Configuration: Are debug modes, verbose error messages, and development-only settings gated by environment?
- File operations: Are file paths sanitized? Are uploads validated for type and size?
- External calls: Are outbound URLs restricted to allowed domains? Are external API responses validated?
- Error handling: Do error messages expose stack traces, internal paths, or system details to end users?
- Dependencies: Are any newly introduced dependencies known to have current CVEs?
Learning tip: Encode this checklist as a PR template comment block in your repository. Every PR that includes AI-generated code gets a checklist comment automatically generated. This prevents the checklist from being skipped under time pressure.
Hands-On: Performing a Security Review on AI-Generated Code
Step 1: Generate code with a prompt that is security-naive.
Start by generating code that is likely to have security issues:
Write a Node.js Express endpoint that takes a user ID and a search query as URL parameters, searches a PostgreSQL database for records matching that user and query, and returns the results as JSON.
Expected result: A functional endpoint. Note whether it uses string interpolation in the SQL query and whether it includes any authorization check on the user ID parameter.
Step 2: Run the structured security review prompt.
Review the following Express endpoint code for security vulnerabilities. Check specifically for:
1. SQL injection via string interpolation or concatenation
2. Missing authorization check (is the requesting user verified to be the user whose records are being fetched?)
3. Missing input validation on the search query (length limits, character restrictions)
4. Information disclosure in error responses
For each issue, show the vulnerable line, explain the attack, and provide a corrected version.
[PASTE THE GENERATED CODE HERE]
Expected result: The model will typically identify the SQL injection (if present), note the missing IDOR check, and flag unvalidated query parameters. Compare this output to your own manual review — did it catch the same things?
Step 3: Apply the fixes and verify.
Take the corrected code suggested by the security review and apply it. Then run the adversarial red team prompt:
You are a penetration tester. The following Node.js endpoint has had SQL injection fixed and an authorization check added. Attempt to find remaining vulnerabilities. What attacks could still succeed against this code?
[PASTE CORRECTED CODE]
Expected result: A second pass may surface additional issues — rate limiting on the endpoint, error message verbosity, missing pagination that could allow large data dumps.
Step 4: Document findings as PR comments.
Summarize the security review findings for the following code change as GitHub PR review comments. Each comment should: reference the specific line number range, describe the vulnerability in one sentence, explain the risk in one sentence, and suggest the fix. Use the GitHub PR review comment format.
Findings:
[PASTE YOUR REVIEW FINDINGS]
Expected result: Formatted PR comments ready to paste into your code review tool.
Key Takeaways
- AI-generated code is optimized for functionality, not security — it systematically produces code that works on the happy path but is naive about adversarial input and authorization.
- The OWASP Top 10 provides a practical checklist for reviewing AI-generated code; the most common AI-introduced vulnerabilities are injection, broken access control, authentication failures, and security misconfiguration.
- Framing security review prompts as adversarial exercises ("how would an attacker exploit this?") produces significantly more useful findings than asking "is this secure?"
- Four patterns always warrant manual review: user input handling, authorization decisions, file operations, and external API calls.
- A PR-level security checklist encoded as a template creates consistent review coverage without relying on individual memory or discipline.