Vibe Coding and the Security Debt It Creates
The Speed Trap
"Vibe coding" - the practice of describing what you want to an AI and letting it generate code - has fundamentally changed how software gets built. Developers who used to write 200 lines of code per day now ship 2,000. Prototypes that took weeks take hours. Startups go from idea to MVP 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. These are real patterns observed in AI-generated code across multiple models and multiple studies.
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
- Generic error message is actually fine (doesn't reveal whether username exists)
- Session fixation vulnerability (no session regeneration)
- No input validation on username/password length
Seven security issues in thirteen 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.
Studies of AI-generated code show that 30-40% of code suggestions contain at least one security vulnerability. The most common issues are injection flaws (SQL, command, XSS), broken authentication patterns, and missing input validation. The 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 are based on 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 |
| Typosquatting risk | AI occasionally suggests package names that are close but not exact | Potential malicious package installation |
| Excessive dependencies | AI imports full libraries for single functions | Larger attack surface |
| Pinning omission | AI rarely pins dependency versions | Dependency confusion attacks |
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 10x more code, reviewers face 10x more material. Review quality drops as volume increases. Studies show that code review effectiveness drops significantly when review sessions exceed 60-90 minutes or 400 lines of code. AI-generated pull requests routinely exceed both thresholds.
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 - 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
Organizations adopting AI-assisted development are seeing productivity metrics improve dramatically. Lines of code, features shipped, time-to-deploy - all trending up. But these metrics don't capture security debt.
Here's an attempt to quantify the hidden costs:
Visible Benefit:
- 3x increase in feature velocity
- 50% reduction in development time
- Faster time to market
Hidden Costs (typically unmeasured):
- Vulnerabilities per 1000 lines of code: 2-5x increase
- Time to detect AI-introduced vulnerabilities: 6-18 months
- Cost to remediate vs. prevent: 10-30x multiplier
- Compliance risk from unreviewed code: unquantified
- Incident response costs from exploited AI-generated vulns: ???
The math is straightforward. If AI-generated code has 2-5x more vulnerabilities per line, and you're producing 3-10x more code, your vulnerability surface could be increasing by 6-50x. Even if only 1% of those vulnerabilities are exploitable, the absolute number of exploitable issues is growing rapidly.
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 - which AI models tend to prefer.
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 almost never includes security-relevant logging. Failed login attempts, permission denials, input validation failures, unusual access patterns - these events 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. Instead of "create 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. This doesn't mean you 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 Deepak Gupta's 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 rarely pins versions, 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.