Vibe Coding Is Fun Until Someone Drops a Bobby Tables on Your App
Vibe coding with AI is incredibly productive, but it's also quietly shipping vulnerabilities. Here's what's getting missed and a prompt to fix it.
You asked Claude to build you a full-stack app. Fifteen minutes later, you've got a working login page, a database, an API, and a dashboard. You're flying. You're vibe coding.
Then someone submits <script>alert('owned')</script> into your contact form and your whole house of cards starts to wobble.
Look — I'm not here to kill the vibe. AI-assisted coding is genuinely one of the most exciting shifts in how we build software. But there's a pattern I keep seeing: developers (and especially non-developers building with AI) are shipping applications that work beautifully on the happy path and are catastrophically vulnerable on every other path.
Let's talk about what's getting missed, why it's getting missed, and what to do about it.
Why Vibe Coding Has a Security Blind Spot
When you prompt an AI to "build me a user registration system with a PostgreSQL database," the AI optimises for making it work. And it does. Impressively well, actually.
But the AI is responding to your prompt, and your prompt didn't say:
- "Make sure all inputs are sanitised against XSS"
- "Implement proper CORS policies"
- "Use parameterised queries to prevent SQL injection"
- "Rate-limit the API endpoints"
- "Validate and escape every single user input on both client and server"
You didn't ask, so it didn't build it. Or worse — it built a surface-level version that looks secure but isn't.
This isn't the AI's fault. It's a gap in the workflow. And it's a gap that gets people burned.
The Hit List: What's Getting Shipped Without Protection
1. SQL Injection
The classic. The granddaddy. And it's still showing up in AI-generated code.
I've seen Claude and other models generate code like this when asked quickly:
query = f"SELECT * FROM users WHERE email = '{user_input}'"
cursor.execute(query)
That's a direct injection vector. Someone submits ' OR '1'='1' -- as their email and they've just dumped your users table. Or worse.
What it should look like:
cursor.execute("SELECT * FROM users WHERE email = %s", (user_input,))
Parameterised queries. Always. No exceptions. If your AI-generated code is concatenating strings into SQL, you have a problem.
2. Cross-Site Scripting (XSS)
Every text field is a potential attack surface. Every single one.
When AI builds a form that saves user input and displays it later — a comment system, a profile page, a chat feature — it frequently skips output encoding. The data goes in raw and comes out raw.
// Dangerous: rendering user content directly
element.innerHTML = userComment;
Now someone's running arbitrary JavaScript in every other user's browser. Session hijacking, cookie theft, redirects to phishing pages — all on the table.
What needs to happen:
- Sanitise input on the way in (strip or escape HTML entities)
- Escape output on the way out (use
textContentinstead ofinnerHTML, or use a library like DOMPurify) - Implement a Content Security Policy (CSP) header as a safety net
3. CORS Misconfigurations
This one is rampant. When the AI sets up an Express or FastAPI backend, it often throws in a wildcard CORS policy to "make things work":
app.use(cors({ origin: '*' }));
During development? Fine. Shipped to production? You've just told every domain on the internet that it's welcome to make requests to your API. Combined with cookie-based auth, this is a disaster.
What it should look like:
app.use(cors({
origin: ['https://yourdomain.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
}));
Explicit origins. Explicit methods. No wildcards in production. Ever.
4. API Safety & Rate Limiting
AI-generated APIs almost never include:
- Rate limiting — Without it, someone can brute-force your login endpoint or scrape your entire database through a list endpoint.
- Input validation — The API accepts whatever JSON shape you throw at it and tries to process it.
- Authentication checks on every route — I've seen generated code where the auth middleware is applied to the login route but not to the actual protected resources.
- Proper error handling — Stack traces and internal error messages get sent directly to the client, leaking your architecture.
If your API endpoint doesn't validate the shape, type, and bounds of every piece of incoming data, it's not an API — it's an open invitation.
Use something like Zod (TypeScript), Pydantic (Python), or Joi (Node) to validate every request body. Add rate limiting with libraries like express-rate-limit or your cloud provider's built-in tools.
5. Authentication & Session Management
This is where things get genuinely scary. AI-generated auth systems frequently:
- Store passwords in plain text or with weak hashing (MD5, SHA-1)
- Generate JWTs with weak or hardcoded secrets (
secret123) - Never expire tokens
- Store tokens in localStorage (accessible to XSS attacks)
- Skip CSRF protection entirely
The basics that must be present:
- Bcrypt or Argon2 for password hashing
- Strong, environment-variable-stored JWT secrets
- Token expiration and refresh token rotation
- HttpOnly, Secure, SameSite cookies for token storage
- CSRF tokens for state-changing requests
6. File Uploads
If your app accepts file uploads and the AI didn't add validation, someone's uploading a PHP shell or a massive file that crashes your server.
- Validate file types on the server (not just the extension — check magic bytes)
- Enforce size limits
- Never serve uploaded files from your application directory
- Use a storage service like S3 with proper access controls
7. Environment Variables & Secrets
I've lost count of how many AI-generated projects include API keys directly in the source code. Sometimes the AI even generates a .env file but never adds .env to .gitignore.
Always check:
- No secrets in source code
.envin.gitignore- Different secrets for development and production
- Secrets rotated regularly
The Uncomfortable Truth
The code works. The demo is impressive. The vibe is immaculate.
But "it works" and "it's secure" are completely different statements. The gap between them is where breaches happen, data leaks, and real people get hurt.
This is especially critical for Canadian developers and businesses — with PIPEDA and evolving provincial privacy legislation, a data breach isn't just embarrassing, it's a legal liability.
The Fix: A Security Audit Prompt
Here's the good news — the same AI that wrote the vulnerable code can audit it. You just need to ask properly.
Below is a comprehensive prompt you can give to Claude to review your vibe-coded project. Copy the whole thing, paste your code in where indicated, and let it rip:
You are a senior application security engineer performing a thorough security audit. Analyse the following codebase with extreme scrutiny. Assume the code will be deployed to production and exposed to the public internet.
Check for ALL of the following vulnerability categories and report every instance found:
## Input Handling
- SQL injection (string concatenation in queries, missing parameterisation)
- Cross-site scripting (XSS) — stored, reflected, and DOM-based
- Command injection
- Path traversal
- Unvalidated redirects
- Missing input validation (type, length, format, bounds)
- Missing output encoding/escaping
## Authentication & Authorisation
- Weak password hashing (MD5, SHA-1, plain text)
- Hardcoded or weak JWT secrets
- Missing token expiration
- Insecure token storage (localStorage for sensitive tokens)
- Missing CSRF protection
- Broken access controls (missing auth checks on routes, IDOR vulnerabilities)
- Missing brute-force protection on login/auth endpoints
## API Security
- Missing rate limiting
- Missing request body validation
- Overly permissive CORS policies (wildcard origins)
- Verbose error messages leaking internal details
- Missing HTTPS enforcement
- Mass assignment vulnerabilities
## Data & Infrastructure
- Secrets or API keys hardcoded in source code
- Missing .env in .gitignore
- Sensitive data logged or exposed in responses
- Missing security headers (CSP, X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security)
- Insecure file upload handling
- Missing database connection encryption
## Session Management
- Insecure cookie configuration (missing HttpOnly, Secure, SameSite flags)
- Session fixation vulnerabilities
- Missing session invalidation on logout
## Heavy Duty Identifiers
Identify all possible security vulnerabilities in this system. This includes things like SQL injection, NoSQL injection, exposed API keys or secrets, missing authentication or weak authorization, insecure direct object references, open endpoints, rate limiting issues, improper input validation or sanitization, XSS, CSRF, misconfigured CORS policies, file upload vulnerabilities, and dependency risks. For each vulnerability you find, explain exactly how it could be exploited in a real-world scenario. Show a simple example of an attack such as a request, payload, or method. Rate the severity and explain the business impact like data leaks, account takeovers, revenue loss, or crashes. Evaluate how the system behaves under load. Assume this app suddenly gets 10,000 users in an hour. Identify what breaks, where the bottlenecks are, and what would cause failed requests or downtime. Analyze trust and data risks. Explain what user data is at risk if compromised, whether there are compliance concerns like GDPR or PIPEDA, and whether there are gaps in logging, monitoring, or alerting. Provide a prioritized fix plan. List what should be fixed first, explain exactly how to fix it, and suggest specific tools, libraries, or architectural improvements where relevant Think like an attacker. If you had 24 hours to break this app, explain what you would target first and the fastest way to cause damage or extract value. Be brutally honest. Assume this app will go viral and be targeted immediately. Do not simplify your answer.
For each vulnerability found:
1. State the vulnerability type and severity (Critical / High / Medium / Low)
2. Show the exact code location
3. Explain the attack scenario in plain language
4. Provide the corrected code
After the audit, provide a prioritised remediation checklist ordered by severity.
Here is the codebase to audit:
[PASTE YOUR CODE HERE]
This prompt isn't gentle. It's not supposed to be. It's designed to catch the things that vibe coding skips over.
Keep the Vibe, Add the Vigilance
I genuinely love what AI-assisted development enables. The speed, the accessibility, the way it lowers barriers to building things — it's extraordinary. I don't want anyone to stop vibe coding.
But I want people to vibe code and then audit. Build fast, then review carefully. Use the AI for both phases.
Think of it like this: the first pass with AI is the rough draft. The security audit is the edit. You wouldn't publish a first draft, and you shouldn't deploy one either.
If you're building something with AI and want a second set of eyes on the security side — or if you're looking for someone to help you build it right from the start — get in touch. I'd love to help you ship something that's both fast and safe.