Vibe Coding and the Security Debt It Creates
The Speed Trap
Andrej Karpathy coined "vibe coding" in a February 2025 post. You describe what you want, accept what the AI writes, and "forget that the code even exists." The term now covers most AI-first development, and it has changed how software gets built. Prototypes that took weeks can take hours. Founders go from idea to working demo over a weekend.
The speed is intoxicating. It's also creating a security debt that the industry isn't accounting for.
When a developer writes code by hand, they make conscious decisions about security at every step. Should I parameterize this query? Should I validate this input? Should I hash this password? These decisions are imperfect (developers miss things), but they represent active engagement with the security implications of each line of code.
When an AI generates code from a natural language prompt, those decisions happen invisibly. The developer sees working code and moves on. The security choices embedded in that code, good or bad, are accepted implicitly. And because the code works, there's enormous pressure to ship it without the scrutiny that hand-written code receives.
What AI-Generated Code Actually Looks Like (Security-Wise)
Let's look at what happens when you ask an AI to generate common application patterns. The snippets below are illustrative, written to show the patterns that security studies of AI-generated code keep finding.
Example 1: SQL Queries
Prompt: "Write a function to search users by name"
AI-generated code (common output):
def search_users(name):
query = f"SELECT * FROM users WHERE name LIKE '%{name}%'"
return db.execute(query)
This is textbook SQL injection. The name parameter is interpolated directly into the SQL string. An attacker providing '; DROP TABLE users; -- as the name could destroy the database.
A security-aware developer would write:
def search_users(name):
query = "SELECT * FROM users WHERE name LIKE %s"
return db.execute(query, (f"%{name}%",))
The parameterized version prevents SQL injection. But the AI wasn't asked about security. It was asked to search users. And the insecure version works perfectly for the stated goal.
Example 2: Authentication
Prompt: "Create a login endpoint"
AI-generated code (common output):
@app.route('/login', methods=['POST'])
def login():
username = request.form['username']
password = request.form['password']
user = db.query(f"SELECT * FROM users WHERE username='{username}'")
if user and user.password == password:
session['user_id'] = user.id
return redirect('/dashboard')
return 'Invalid credentials', 401
Security issues in this snippet:
- SQL injection in the query (again)
- Plaintext password comparison (no hashing)
- No rate limiting on login attempts
- No CSRF protection
- Session fixation vulnerability (no session regeneration)
- No input validation on username or password length
One thing is right: the generic error message doesn't reveal whether the username exists. That still leaves six security issues in nine lines of code. The code works. A user can log in. But it would fail any security review.
Example 3: File Upload
Prompt: "Add file upload functionality"
AI-generated code (common output):
@app.route('/upload', methods=['POST'])
def upload():
file = request.files['file']
file.save(os.path.join('uploads', file.filename))
return 'File uploaded successfully'
Security issues:
- No file type validation (user could upload executable files)
- No file size limit (denial of service)
- Path traversal vulnerability (
filenamecould contain../../etc/passwd) - No virus scanning
- Files saved with original filename (could overwrite existing files)
- Upload directory likely served publicly
Each of these examples represents code that an AI generates confidently, that works for the happy path, and that contains serious vulnerabilities.
The research is consistent. An NYU study of GitHub Copilot, Asleep at the Keyboard, found about 40% of 1,689 generated programs vulnerable. Veracode's 2025 GenAI Code Security Report tested more than 100 models on 80 tasks. Given a choice between a secure and an insecure method, the models chose the insecure one 45% of the time. AI generates functional code, but "functional" and "secure" are different requirements.
The Dependency Problem
AI-generated code doesn't just have inline security issues. It also makes dependency choices that create supply chain risks.
When you ask an AI to "create a web scraping tool" or "build a PDF generator," it imports packages. Those package choices come from the training data, which reflects what was popular, not what was secure.
Common patterns in AI-generated dependency choices:
| Issue | What Happens | Security Impact |
|---|---|---|
| Outdated packages | AI suggests packages with known CVEs | Known vulnerabilities in production |
| Unmaintained packages | AI picks packages abandoned years ago | No security patches available |
| Hallucinated packages | AI suggests package names that don't exist | Attackers register the name and wait ("slopsquatting") |
| Excessive dependencies | AI imports full libraries for single functions | Larger attack surface |
| Pinning omission | AI often leaves dependency versions unpinned | Unreproducible builds, dependency confusion |
The hallucinated-package problem is measurable. A USENIX Security 2025 study generated 576,000 code samples with 16 models. On average, at least 5.2% of suggested packages from commercial models and 21.7% from open-source models did not exist. The researchers collected 205,474 unique hallucinated package names, each one a name an attacker could register.
Dependency Confusion in AI-Generated Code
Dependency confusion is particularly dangerous with AI-generated code. In a dependency confusion attack, an attacker publishes a malicious package to a public registry with the same name as an internal company package. If the build system checks the public registry first, it pulls the malicious package instead of the internal one.
AI coding assistants don't know about your internal packages. When they generate import statements, they reference public packages. If a developer uses AI-generated code that imports a package name that happens to match an internal package, and their build system is misconfigured, they've created a dependency confusion vulnerability, guided by AI.
Who Reviews AI-Generated Code?
This is the fundamental question, and the answer is concerning.
The Review Gap
Traditional code review works because humans read code they didn't write and ask questions: Why did you do it this way? Did you consider this edge case? What happens if this input is malicious?
AI-generated code disrupts this process in several ways:
Volume overwhelms reviewers. When a developer produces several times more code, reviewers face several times more material, and review quality drops. SmartBear's guidance, drawn from a large code review study at Cisco, is to review no more than 200 to 400 lines at a time, for no more than 60 to 90 minutes. AI-generated pull requests routinely exceed both.
Ownership ambiguity. When a reviewer asks "why did you do it this way?" about AI-generated code, the developer often can't explain the AI's reasoning. They accepted the suggestion because it worked. This undermines the knowledge transfer that makes code review valuable.
Familiarity bias. Developers who generated the code with AI tend to trust it more than they should. They've already tested the happy path, and it works. The motivation to scrutinize deeply is lower than for code they received from a colleague they might want to challenge.
Security as afterthought. Most code review focuses on functionality, architecture, and style. Security review is a specialized skill that most developers lack. AI-generated code gets the same (insufficient) security scrutiny as human-written code, but it needs more.
What Happens in Practice
Developer's workflow with AI coding:
1. Describe feature in natural language
2. AI generates code
3. Developer tests happy path: "Does it work? Yes."
4. Developer commits code
5. PR review focuses on "does this implement the feature?"
6. Security review: [SKIPPED, no dedicated security reviewer]
7. Code ships to production
8. Vulnerability discovered months later (or never)
The missing step, dedicated security review of AI-generated code, is where the debt accumulates. Every feature shipped without security review is a bet that the AI got security right. Over hundreds of features, some of those bets will lose.
The Hidden Cost of Speed
Teams adopting AI-assisted development usually report better productivity metrics. Lines of code, features shipped and time to deploy all trend up. None of those metrics capture security debt.
Here is how the ledger looks when you write down both sides:
Visible benefits (measured):
* More features shipped per sprint
* Less time from idea to deploy
* Faster time to market
Hidden costs (typically unmeasured):
* Flaws introduced per feature
* Time until AI-introduced flaws are found
* Cost to fix in production versus at review
* Compliance exposure from unreviewed code
* Incident costs when one of those flaws is exploited
The arithmetic works against you. Suppose the flaw rate per line stays where Veracode measured it and your output doubles. Unless review capacity doubles too, the number of flaws reaching production doubles. Speed multiplies whatever your process lets through.
Track two additional metrics for AI-assisted development: (1) vulnerabilities found in AI-generated code vs. human-written code, and (2) the ratio of AI-generated code that receives security review vs. total AI-generated code. These metrics make the security debt visible.
Common Vulnerability Patterns in AI-Generated Code
Certain vulnerability categories appear consistently in AI-generated code. Knowing these patterns helps focus security reviews.
1. Injection Flaws
SQL injection, command injection, LDAP injection, XPath injection. AI-generated code frequently constructs queries and commands using string concatenation instead of parameterized approaches. This is partly because training data includes both patterns, and the string concatenation approach is more concise.
2. Broken Access Control
AI-generated endpoints often lack authorization checks. The AI implements the functionality (create, read, update, delete) without verifying that the requesting user has permission to perform the action on the requested resource. This results in Insecure Direct Object Reference (IDOR) vulnerabilities where any authenticated user can access any other user's data.
3. Security Misconfiguration
AI-generated configurations tend toward convenience over security. Default passwords, debug modes enabled, CORS set to allow all origins, verbose error messages exposed to users. These are the settings that make development easy and production dangerous.
4. Missing Cryptographic Controls
AI-generated code frequently:
- Uses weak hashing algorithms (MD5, SHA1) for sensitive data
- Implements custom cryptography instead of using established libraries
- Stores encryption keys alongside encrypted data
- Uses ECB mode for block ciphers (which preserves patterns in encrypted data)
- Generates cryptographic keys with insufficient entropy
5. Insufficient Logging and Monitoring
AI-generated code rarely includes security-relevant logging unless you ask for it. Failed login attempts, permission denials, input validation failures and unusual access patterns go unlogged because the AI wasn't asked to implement monitoring.
What "Good" Looks Like
Addressing vibe coding security debt requires changes at multiple levels: the developer, the team, and the organization.
For Developers
Include security requirements in prompts. Don't just ask for "a login endpoint." Prompt with "create a login endpoint with parameterized queries, bcrypt password hashing, rate limiting, CSRF protection, and security event logging." The AI will generate more secure code when security requirements are explicit.
Never accept generated code without understanding it. If you can't explain what each line does and why, don't commit it. You don't need to write every line yourself, but you need to understand every line.
Run security linters on AI-generated code. Tools like Semgrep, Bandit (Python), ESLint security plugins (JavaScript), and Brakeman (Ruby) catch many common vulnerabilities automatically. Make these part of your development workflow, not just your CI pipeline.
For Teams
Establish AI-generated code review guidelines. Create a checklist of security items that must be verified for any PR containing AI-generated code:
- Input validation on all external inputs
- Parameterized queries for all database access
- Authorization checks on all endpoints
- No hardcoded credentials or secrets
- Dependencies pinned and checked against vulnerability databases
- Error handling doesn't leak sensitive information
- Security-relevant events logged
- Rate limiting on authentication and sensitive endpoints
Dedicate security review time. If your team doesn't have a security expert, rotate "security reviewer" responsibility. Even a developer doing their best to think about security catches more than no review at all.
Track AI-generated code separately. Tag or label PRs that contain AI-generated code. This enables you to measure quality differences and focus security review where it's needed most.
For Organizations
Invest in automated security testing. SAST (Static Application Security Testing), DAST (Dynamic Application Security Testing), and SCA (Software Composition Analysis) tools catch a significant portion of AI-generated vulnerabilities. These tools should run automatically in CI/CD pipelines, blocking deployment when critical issues are found.
Implement security guardrails, not gates. Instead of a security review gate that creates a bottleneck, implement guardrails that catch issues early. IDE-integrated security linting, pre-commit hooks that scan for secrets, and automated dependency checking all catch issues before they reach code review.
Define AI coding policies. Which types of code can be AI-generated without additional review? Where is human authorship required? Common boundaries:
| Code Category | AI-Generation Policy |
|---|---|
| Authentication/authorization | Human-written or intensive review |
| Cryptographic operations | Human-written only |
| Input validation | AI-assisted with security linting |
| Business logic | AI-assisted with standard review |
| UI components | AI-generated, standard review |
| Test code | AI-generated, minimal review |
| Infrastructure as code | AI-assisted with security scanning |
The security debt from vibe coding isn't theoretical. It's accumulating in production codebases right now. Every organization using AI-assisted development needs a strategy for managing this debt before it becomes a crisis. For a related discussion on security categories that matter for SaaS products, see my article on enterprise cybersecurity strategy.
The Supply Chain Multiplier
Vibe coding doesn't just create security debt in your own code. It amplifies supply chain risk.
When a developer manually selects a dependency, they (ideally) evaluate its maintenance status, security history, and reputation. When an AI suggests a dependency, the developer often accepts it without evaluation. The AI's recommendation is based on popularity in training data, not security posture.
This creates a compounding effect:
- AI generates code with more dependencies than a human would use
- Each dependency has its own dependency tree
- No human evaluated whether these dependencies are trustworthy
- Some dependencies may be unmaintained, vulnerable, or even malicious
The practical mitigation is to treat dependency selection as a separate, human-reviewed step. Even if the AI writes the code, a human should approve every new dependency added to the project. This is a small overhead that prevents significant supply chain risk.
Additionally, pin all dependency versions and use lockfiles. AI-generated code often leaves versions unpinned, which means the exact packages in your development environment may differ from production. Version pinning ensures reproducible builds and prevents dependency confusion attacks.
The Bigger Picture
Vibe coding isn't going away. AI-assisted development will become the default way software is built. The question isn't whether to use it. It's how to use it without creating unacceptable security risk.
The organizations that will thrive are those that treat AI-generated code like any other third-party input: useful, but not trusted by default. They'll build automated security testing into every pipeline, train developers to think critically about AI suggestions, and measure security debt as deliberately as they measure feature velocity.
The organizations that simply count shipped features without counting shipped vulnerabilities will learn the hard way that speed without security is just moving faster toward your next incident.