June 27, 2026

Secure Vibe Coding: How to Stop AI From Slipping Vulnerabilities Into Your Code

Photo of Marco Orta Marco Orta | 11 min read
Compartir
Screen of AI-generated code with a security shield and vulnerability alerts flagged for review before committing

The code AI writes almost always works, but it isn’t always secure: 2026 studies find that somewhere between 40% and 60% of model-generated code contains an OWASP Top 10 vulnerability. The problem isn’t AI itself —it’s excellent at speeding things up— but accepting what it suggests without reviewing it. In this guide I’ll show you the flaws it repeats over and over and the exact checklist you should run before you commit.

Vibe coding —programming by describing what you want to an agent and accepting whatever it returns— has tripled or quadrupled the speed at which we write code. The uncomfortable detail: according to an analysis of Fortune 50 companies, those same developers introduce security findings at a rate ten times higher than when they wrote by hand. More code, faster… and more attack surface.

Why AI generates insecure code

A language model optimizes for one thing: producing code that looks correct and that works for the happy path you described. Security is almost never in the prompt, so it isn’t in the answer either. AI doesn’t “think” about the attacker who drops quotes into a form, the user who changes an id in the URL, or the secret it just wrote in plain text.

On top of that comes false confidence: the code compiles, the happy-path tests pass, and the demo looks complete. It seems finished long before it has actually been challenged. And the numbers back it up: 92% of developers already use AI daily, but only 29% trust the code it produces… and even so, barely 48% always review it before pushing.

💡 The golden rule. AI is a brilliant, lightning-fast junior who has never read the OWASP Top 10. It saves you hours, but you’re still the senior who signs off on the commit. If you don’t understand a line it suggested, don’t push it.

The 7 vulnerabilities AI introduces again and again

These are the ones that show up most often in AI-generated code. Learn them: reviewing while specifically looking for them is far faster than “reading everything to see if something smells off”.

1. Injection (SQL and commands)

The classic. AI concatenates user variables directly into a query or a system command because it’s the “shortest” way to write it:

// ❌ What the AI suggests: SQL injection served on a silver platter
db.query(`SELECT * FROM users WHERE email = '${email}'`);

// ✅ The right way: parameterized queries
db.query('SELECT * FROM users WHERE email = ?', [email]);

The same applies to exec(), eval() and building shell commands out of user data. Rule: if a value comes from outside, it’s never interpolated into a query or a command; it’s passed as a parameter.

2. Broken access control (IDOR)

AI implements the business logic, but forgets to ask “is this user allowed to do this?”. The typical result is an endpoint that trusts whatever id it’s handed:

// ❌ Anyone can read anyone's invoice just by changing the id
app.get('/api/facturas/:id', (req, res) => {
  return res.json(getFactura(req.params.id));
});

// ✅ Check ownership of the resource
app.get('/api/facturas/:id', requireAuth, (req, res) => {
  const factura = getFactura(req.params.id);
  if (factura.userId !== req.user.id) return res.sendStatus(403);
  return res.json(factura);
});

It’s the #1 vulnerability in the OWASP Top 10 and the one AI overlooks most naturally, because it “works” perfectly in the demo.

3. Hardcoded secrets

To make it “work right now”, AI embeds the API key, the database password or the token directly in the code. AI-assisted commits expose secrets at twice the rate of hand-written ones (3.2% versus 1.5%).

// ❌ A secret in the repo is a compromised secret
const stripe = new Stripe('sk_live_51H...');

// ✅ Environment variables, always
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

And remember: a secret that ever touched the Git history is already burned, even if you delete it in the next commit. You have to rotate it.

4. Hallucinated dependencies (slopsquatting)

This one is new and dangerous. Models “invent” package names that don’t exist: nearly 20% of AI code samples import at least one hallucinated dependency, and 43% of those fake names recur on every run. Attackers know this and register those names with malicious code inside, waiting for someone to run npm install blindly. It’s called slopsquatting.

Before installing what the AI suggests, verify that the package actually exists, who maintains it, and how many downloads it has. If you’ve never heard of that name, be suspicious.

5. XSS: unescaped output

AI renders whatever the user typed straight into the HTML, without sanitizing it. A Georgetown study of five large models found XSS in most of the samples analyzed.

// ❌ If the comment contains <script>, it executes
<div dangerouslySetInnerHTML={{ __html: comentario }} />

// ✅ Let the framework escape it, or sanitize with DOMPurify
<div>{comentario}</div>

6. Weak cryptography

AI drags old patterns out of its training data: hashing passwords with MD5 or SHA-1, using Math.random() to generate tokens, or encrypting with broken algorithms.

// ❌ MD5 for passwords: broken for over a decade
const hash = crypto.createHash('md5').update(password).digest('hex');

// ✅ bcrypt / argon2 for passwords; cryptographic random for tokens
const hash = await bcrypt.hash(password, 12);
const token = crypto.randomBytes(32).toString('hex');

If you need to quickly check which algorithm produced a hash, my MD5 and SHA Hash Generator lets you see it instantly —and along the way you’ll understand why MD5 is no good for secrets.

7. Insecure configuration

CORS wide open to *, debug mode left on in production, cookies without HttpOnly/Secure, and almost always zero HTTP security headers. AI builds the app, but it doesn’t harden it.

// ❌ CORS that accepts everyone
app.use(cors({ origin: '*' }));

// ✅ Explicit allowlist
app.use(cors({ origin: ['https://tudominio.com'] }));

When you finish your vibe-coded app, run it through my HTTP Security Headers analyzer: it gives you a grade from A to F and tells you which headers (HSTS, CSP, X-Frame-Options…) you’re missing. Most AI-generated projects fail here without knowing it.

The checklist: what to review before every commit

You don’t need to audit line by line. Run this mental filter —or paste it into your pull request template— over every block you accept from the AI:

  1. User input → is every query parameterized and does every command avoid direct interpolation?
  2. Authorization → does each endpoint that touches a resource check that this user can view/edit it?
  3. Secrets → is there any key, token or password in the code? Out it goes, into environment variables.
  4. Dependencies → does each new package actually exist? Who maintains it and how many downloads does it have?
  5. Output → is everything rendered into the HTML escaped or sanitized?
  6. Cryptography → passwords with bcrypt/argon2 and randomness with crypto, never MD5 or Math.random()?
  7. Configuration → CORS locked down, debug off, secure cookies and security headers in place?

If you work with tokens, the JWT Decoder and Verifier helps you confirm that your authentication signs and expires tokens the way it should, without pasting them into a third-party site.

Automate the defense: let the machine review the machine

Reviewing by eye doesn’t scale. The realistic move is to put automatic safety nets in place that run on every commit, so a slip never reaches production:

  • Secret scanner (Gitleaks, TruffleHog) in a pre-commit hook: blocks the commit if it detects a key.
  • SAST (Semgrep, CodeQL, Snyk Code): static analysis that catches injection, XSS and broken access control.
  • Dependency audit (npm audit, pip-audit, Dependabot): detects vulnerable packages… and non-existent ones.
  • Mandatory CI: no PR merges if any of the above fails.

The golden rule of 2026 with agents: least privilege and sandbox. If you let an agent run commands, give it access only to what it needs and in an isolated environment. An agent with admin permissions and a hallucination is a bad combination.

The right mindset matters more than the tool

All this technology is worth little if your workflow is “accept everything and pray”. The mindset shift is simple: AI proposes, you decide. Treat it like that lightning-fast junior: you review their work, you demand they understand what they deliver, and you’re the one who answers for the code that ships.

If you build mobile apps, the same principles are organized in the OWASP MASVS standard —I covered it in my guide to mobile application security—. And once your app is on a domain, close the loop by auditing its email, DNS and SSL with these 7 free tools.

In summary

Vibe coding is here to stay, and it’s one of the biggest productivity boosts of the decade. But speed without review is security debt disguised as progress. The good news: with the checklist above, a couple of automated scanners and the habit of always reviewing, you keep all the speed and almost none of the risk.

Do you have an app that was built “on vibes” and you’re not sure whether it’s secure? I can review it or build it properly from the ground up: take a look at my custom web development service or, if you want to bring AI into your business without opening holes, my automation and AI service.

Frequently asked questions

Is AI-generated code secure? It works, but it isn’t secure by default: nearly half of it ships with an OWASP Top 10 vulnerability. You should always review it before committing.

Where do I start reviewing? With the three most serious and frequent ones: injection (use parameterized queries), access control (check permissions on every endpoint) and hardcoded secrets (move them to environment variables).

Have you caught the AI slipping a vulnerability into your code? Tell me which one it was —and if you’ve already run your site through the security headers analyzer, what grade you got.

Compartir

Search

Tags