Speed Is the Point — Until It Isn't
Vibe coding is genuinely great. You describe what you want, your AI tool of choice — Cursor, Copilot, Claude, pick your poison — spits out something that mostly works, you tweak it, ship it. Features that used to take days land in hours. It feels like cheating, in the best way.
The problem is that AI models optimize for code that runs, not code that's safe. When you're moving fast and accepting suggestions without reading them closely, you can ship working features with gaping security holes — and not find out until something goes wrong.
This isn't a knock on AI tools. It's a knock on moving fast without a checklist. Here's what to watch for.
The Most Common Security Issues in AI-Generated Code
1. Hardcoded Secrets
Ask an AI to scaffold a project that connects to an API and there's a decent chance it'll include something like:
❌ secret hardcoded in sourceconst apiKey = "sk-abc123youractualkey";Convenient for demos. A disaster if that file ends up in a public repo, a Docker image, or even just version control that you later share. Secrets in code are one of the most common causes of credential leaks, and they're embarrassingly easy to miss in a fast-moving codebase.
What to do: Use environment variables. Always. And audit your repo for any string that looks like a key, token, or password — gitdoctor.io can scan for these automatically before they leave your machine.
2. Missing Auth Checks
AI-generated route handlers are often optimized for the happy path. They do the thing they're asked to do. What they don't always do is verify that the person making the request is allowed to make it.
❌ no ownership check — any user ID works// anyone can call this and get any user's data
app.get("/api/user/:id", async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json(user);
});No session check. No ownership verification. Anyone who knows (or can guess) a user ID can pull that data. This pattern shows up constantly in AI-generated REST APIs and Next.js route handlers.
What to do: Before any handler returns data, ask yourself: who is allowed to see this, and am I checking that?It's a simple habit that prevents a wide class of vulnerabilities.
3. SQL Injection
Modern AI tools generally know about parameterized queries — but they don't always use them, especially when generating quick helper functions or adapting code from a different context. If you're using a raw query builder or a less-common ORM, the model might fall back to string concatenation:
❌ user input interpolated into raw SQLquery = f"SELECT * FROM users WHERE email = '{user_input}'"
# classic. completely avoidable.What to do: Never interpolate user input directly into queries. Use parameterized statements or an ORM that handles escaping for you — and treat any raw query in AI-generated code as guilty until proven innocent.
4. Exposed API Routes
When you ask an AI to "add an admin endpoint" or "create a route to delete all records," it often creates exactly that — no access control, no environment guard, nothing stopping a curious user from hitting /api/admin/reset in production.
This also happens with debugging routes. A /api/debug/env endpoint that dumps environment variables might be perfectly useful in local dev, and catastrophic if it ships.
What to do: Any route with elevated privileges needs explicit auth middleware. Any debug route needs to be gated behind an environment check or removed before shipping.
5. No Rate Limiting
AI tools rarely add rate limiting unprompted. Your login endpoint, your password reset flow, your public-facing API — all wide open to brute force or abuse if you don't add it yourself.
✅ rate limiter applied to sensitive endpointsimport rateLimit from 'express-rate-limit';
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10,
message: 'Too many attempts. Try again later.',
});
app.post('/api/auth/login', loginLimiter, loginHandler);What to do:Add rate limiting to any endpoint that's expensive to hit or sensitive to abuse. Libraries like express-rate-limitor Cloudflare's built-in rate limiting make this a 10-minute job.
What Actually Happens When These Get Missed
You don't always find out immediately. Sometimes it's a security researcher who emails you. Sometimes it's a spike in your database bill because someone is scraping user data. Sometimes it's a breach disclosure you have to send to your users.
The ones that sting most are the preventable ones — a hardcoded API key in a public GitHub repo, spotted and rotated by a bad actor before you noticed. A missing auth check that let users access each other's data for weeks before someone reported it.
These aren't edge cases. They're the kind of thing that happens when the code works fine in testing, ships fast, and nobody looked closely at what the AI actually wrote.
How to Catch These Before They Bite You
Read what you ship.This sounds obvious, but vibe coding's whole appeal is trusting the output. Get in the habit of doing a focused security read before merging anything that touches auth, data access, or external APIs. You're not auditing every line — you're looking for the patterns above.
Use static analysis. Tools like Semgrep, ESLint security plugins, and Bandit (for Python) catch a lot of the common patterns automatically. Wire them into your CI pipeline and they run without you having to think about it.
Scan your repo for exposed secrets. Before you push, before you make a repo public, before you share a codebase — run a secrets scan. gitdoctor.io is built for exactly this: it analyzes your repository for leaked credentials, vulnerable patterns, and security issues that are easy to miss when you're shipping fast.
Don't skip the boring stuff.Rate limiting, input validation, parameterized queries — these feel like overhead when you're moving fast. They're not. They're the baseline, and the AI won't always add them for you.
Ship Fast. Just Look Both Ways First.
Vibe coding isn't the problem. Shipping without a second look is. The same speed that lets you build a feature in an afternoon can let a security hole go unnoticed for weeks — because everything works, it just doesn't work safely.
Take five minutes before you push. Check for the patterns above. The AI does the heavy lifting — you're still the one responsible for what ships.