The question everyone should be asking
AI coding assistants are writing a significant portion of the code being deployed to production today. GitHub reports that Copilot generates over 40% of code in files where it is active. Cursor, Claude Code, Bolt, and similar tools are being used to build entire applications from scratch.
The productivity gains are real. But a critical question is being overlooked: is the code these tools generate actually secure?
Researchers have been studying this question since 2021, and the findings are consistent. The answer is nuanced, but the trend is clear.
What the research shows
Stanford study: AI assistants produce more insecure code
A landmark 2023 Stanford study ("Do Users Write More Insecure Code with AI Assistants?") found that developers who used AI coding assistants produced significantly more security vulnerabilities than those who coded without AI help.
The study had participants complete coding tasks in Python, JavaScript, and C. The group using AI assistants:
- Produced code with more security vulnerabilities
- Were more likely to believe their code was secure (overconfidence)
- Wrote functional code faster but introduced bugs they did not recognize
The overconfidence finding is particularly concerning. Developers trusted the AI's output and reviewed it less critically than they would review their own code.
GitHub Copilot vulnerability analysis
Research from NYU ("An Empirical Cybersecurity Evaluation of GitHub Copilot's Code Contributions") analyzed Copilot's output across 89 different code generation scenarios. They found that approximately 40% of the generated code contained security vulnerabilities.
The most common vulnerability categories were:
- Injection flaws (SQL injection, command injection, XSS)
- Improper input validation
- Hardcoded credentials and secrets
- Missing authentication and authorization checks
- Insecure cryptographic practices
Pattern: functional but insecure
Across multiple studies, a consistent pattern emerges. AI-generated code:
- Works correctly for the stated requirements
- Handles the happy path well
- Misses edge cases that have security implications
- Omits defensive coding practices unless explicitly prompted
- Reproduces insecure patterns from training data
The AI learned from millions of code repositories, many of which contain vulnerabilities. It learned what code looks like, not what secure code looks like.
Real vulnerability patterns we see
At VibeSec Advisory, we review AI-generated applications regularly. Here are the most common vulnerability patterns we find, with real examples (sanitized from actual assessments):
SQL injection through string concatenation
The AI frequently generates database queries by concatenating user input directly into SQL strings:
// AI-generated code (vulnerable)
const user = await db.query(
`SELECT * FROM users WHERE email = '${req.body.email}'`
);
The secure version uses parameterized queries:
// Secure version
const user = await db.query("SELECT * FROM users WHERE email = ?", [
req.body.email,
]);
This is one of the most well-known vulnerabilities in software security, documented for over 25 years. AI tools still generate vulnerable versions regularly.
Cross-site scripting through unescaped output
AI-generated frontend code often renders user-provided content without sanitization:
// AI-generated code (vulnerable)
<div dangerouslySetInnerHTML={{ __html: comment.body }} />
When the AI sees a requirement like "display user comments with formatting," it reaches for dangerouslySetInnerHTML or .innerHTML because those approaches preserve HTML formatting. But they also execute any JavaScript an attacker injects into a comment.
Missing authorization on API endpoints
This is arguably the most dangerous pattern. AI tools build endpoints that check authentication (is the user logged in?) but skip authorization (does this user have permission to access this specific resource?):
// AI-generated code (vulnerable)
app.get("/api/invoices/:id", requireAuth, async (req, res) => {
const invoice = await db.getInvoice(req.params.id);
res.json(invoice);
});
Want to design your agentic processes properly?
VibeSec helps knowledge worker teams redesign their processes using the APD framework: Skills, Agents, Guardrails, and Schedule. Security is built in, not bolted on. Book a process design session to get started.
Any authenticated user can access any invoice by guessing or iterating through IDs. The fix requires checking that the invoice belongs to the requesting user:
// Secure version
app.get("/api/invoices/:id", requireAuth, async (req, res) => {
const invoice = await db.getInvoice(req.params.id);
if (!invoice || invoice.userId !== req.user.id) {
return res.status(404).json({ error: "Not found" });
}
res.json(invoice);
});
Hardcoded secrets in source code
We regularly find API keys, database passwords, and encryption keys hardcoded directly in AI-generated source files:
// AI-generated code (vulnerable)
const stripe = new Stripe("sk_live_abc123realkey...");
const db = mysql.createPool({
password: "production_password_2026",
});
The AI learned this pattern from thousands of tutorials and Stack Overflow answers that use placeholder values. But when generating code for a real application, it either uses the actual keys provided in context or generates plausible-looking fake ones that developers then replace with real values and commit.
Insecure default configurations
When AI sets up a server or framework, it typically uses the most permissive defaults:
// AI-generated code (vulnerable)
app.use(cors()); // Allows ALL origins
app.use(express.json({ limit: "50mb" })); // Enormous payload limit
Permissive defaults make development easier but create real attack surfaces in production. An open CORS policy lets any website make authenticated requests to your API. A 50MB payload limit enables denial-of-service attacks.
Why AI tools produce insecure code
Understanding the root causes helps explain why this is not a simple problem to fix:
1. Training data reflects reality
AI models are trained on real code from public repositories. A significant portion of public code contains vulnerabilities. The AI learns the statistical distribution of how code is written, not how code should be written.
2. Security conflicts with simplicity
AI assistants are optimized to provide helpful, concise answers. Secure code is inherently more complex than insecure code. Adding input validation, error handling, rate limiting, and authorization checks makes the response longer and harder to understand. The AI is biased toward simpler answers.
3. Context window limitations
AI models process limited context. They may not see the full application architecture, the security requirements, the deployment environment, or the threat model. They generate code for the immediate request without understanding the broader security implications.
4. No adversarial thinking
Security requires thinking like an attacker: "How could someone misuse this?" AI assistants think constructively: "How do I build what was asked for?" This fundamental orientation difference means the AI solves the stated problem without considering how the solution could be exploited.
What you can do about it
The data paints a clear picture, but the solution is not to stop using AI coding tools. The solution is to add a security layer to your workflow.
Prompt for security explicitly
When generating code, include security requirements in your prompt:
- "Generate this with parameterized queries to prevent SQL injection"
- "Include input validation for all user-provided fields"
- "Add authorization checks to verify resource ownership"
- "Use environment variables for all secrets and API keys"
AI tools are significantly better at producing secure code when security is part of the requirement.
Review AI output with a security lens
Do not accept AI-generated code at face value. For each piece of generated code, ask:
- Where does user input enter this code?
- What happens if that input is malicious?
- Who can access this endpoint, and should they all be able to?
- Are there any secrets or credentials in this code?
- What error information would an attacker see?
Use automated security scanning
Tools like npm audit, Snyk, and CodeQL can catch common vulnerability patterns. They are not perfect, but they catch the low-hanging fruit. Run them as part of your build process.
Get a professional security review
Automated tools catch known patterns. A human security reviewer catches logic flaws, authorization bypasses, and business logic vulnerabilities that scanners miss. For any application that handles sensitive data or processes payments, a professional review is not optional.
At VibeSec Advisory, we specialize in reviewing AI-generated applications. We see the same vulnerability patterns repeatedly, which means we find them fast. A focused review before launch can prevent the most common and damaging security issues.
Frequently Asked Questions
What percentage of AI-generated code contains security vulnerabilities?
Research consistently shows approximately 40% of AI-generated code contains security vulnerabilities. The NYU study of GitHub Copilot found this rate across 89 code generation scenarios, and Stanford research found developers using AI assistants produced significantly less secure code while being more confident it was safe.
Is code from Claude, Cursor, or Copilot more secure than code from ChatGPT?
All major AI coding tools produce code with security vulnerabilities at similar rates. The vulnerability types vary — some models handle SQL parameterization better while others handle authentication flows better — but none consistently produce secure code by default. The model matters less than whether you review the output for security.
Should I stop using AI coding tools because of security risks?
No. AI coding tools dramatically accelerate development and the security risks are manageable with the right process. The key is adding a security review layer: prompt your AI for security, review generated code against known vulnerability patterns, run automated scanning, and get professional review before launching applications that handle sensitive data.
Can AI coding tools fix their own security vulnerabilities?
Sometimes. If you identify a specific vulnerability and ask your AI assistant to fix it, it can often generate a correct patch. However, AI assistants are not reliable at finding their own vulnerabilities — they tend to repeat the same insecure patterns. The most effective approach is using a separate security-focused review (human or specialized security agent) to identify issues, then using your AI assistant to implement the fixes.
What are the most common vulnerabilities in AI-generated code?
The top 5 vulnerability patterns we see in AI-generated applications are: missing or misconfigured security headers, hardcoded secrets in source code, insufficient input validation (leading to XSS and injection), broken authentication and session management, and missing authorization checks on API endpoints.
The bottom line
AI-generated code is not secure by default. The research is consistent: about 40% of AI-generated code contains vulnerabilities, developers who use AI assistants produce more insecure code, and they are more confident that their code is safe.
This does not mean AI coding tools are bad. It means they need a security layer. The tools will improve over time, but right now, the responsibility for security falls on the person shipping the code.
If you are building with AI, build security into your process. Prompt for it, review for it, scan for it, and get an expert to verify it. Your users are depending on you.