blinkof.ai Run a free test →
Guide · Security

How to find security holes in a vibe-coded app

AI builders optimize for "it works," not "it's locked down." These are the five holes that turn up again and again — and how to check and close each one.

By Blinkof·7 min read


When you describe a feature and an AI writes the code, security is whatever the model happened to do by default — and the default is usually "make it work," not "lock it down." That's not a knock on the tools; it's just where the gap is. The good news: the holes are predictable. Almost every vibe-coded app leaks in one of five places. You can check all five in about ten minutes.

1. API keys hard-coded in the browser bundle

What it is: a secret key — Stripe, OpenAI, your database service — shipped inside the JavaScript that loads in every visitor's browser. Anything in that bundle is public, full stop.

How to check: open dev tools, go to the Network tab, reload, and view your .js files. Search the source for sk_live, sk_, apiKey, SECRET, and your provider's name. If you find a private key, assume it's compromised.

How to fix: rotate the key immediately, then move the call that uses it to a server function (an API route, edge function, or worker). The browser should only ever hold publishable keys (like Stripe's pk_).

2. A database anyone can read

What it is: a Supabase or Firebase project with Row Level Security (or rules) turned off, so an anonymous visitor can list your users, orders, or messages tables directly.

How to check: with the public anon key that's already in your bundle, try querying your tables as a logged-out user. If rows come back, your data is world-readable.

How to fix: enable RLS on every table and write policies so users can only read their own rows. "Default deny, then allow specifically" is the rule.

3. Missing security headers

What it is: no Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options, or frame protections — which leaves you open to clickjacking, content sniffing, and protocol-downgrade attacks.

How to check: open dev tools, look at the response headers for your page, or run it through a header grader. Most vibe-coded apps score an F.

How to fix: add the headers in your host's config or middleware. On Cloudflare, Vercel, or Netlify it's a few lines: a sensible Content-Security-Policy, Strict-Transport-Security: max-age=31536000, X-Content-Type-Options: nosniff, frame-ancestors 'none', and Referrer-Policy: strict-origin-when-cross-origin.

4. Reflected cross-site scripting (XSS)

What it is: user input that gets rendered into the page as live HTML instead of plain text, letting an attacker run JavaScript in your users' sessions.

How to check: type <img src=x onerror=alert(1)> into your search box, name field, or any input that echoes back. If you get an alert, you have reflected XSS.

How to fix: render user input as text, not HTML. In React, Vue, or Svelte that means not using dangerouslySetInnerHTML, v-html, or @html for untrusted values. A Content-Security-Policy is a strong second layer.

5. API endpoints with no authorization

What it is: a backend route that returns or changes data without checking who is asking. "Logged in" is authentication; "allowed to touch this specific record" is authorization, and it's the one AI builders skip.

How to check: watch the Network tab while you use the app, then re-send a request (e.g. /api/orders/123) with a different id, or with no session at all. If you can read someone else's data, the endpoint is unprotected.

How to fix: on every endpoint, verify the session and that the authenticated user owns the resource before returning or modifying it.

Security in a vibe-coded app isn't usually about exotic exploits. It's the same five doors, left unlocked, over and over.

Check all five at once

Blinkof runs these checks automatically: it reads your shipped bundles for exposed keys, probes your database, grades your headers, fires an XSS payload at your forms, and flags failing requests — then writes each fix as a prompt you can paste straight into Cursor, Claude Code, or Lovable. It's a fast automated pass, not a substitute for a full penetration test, but it catches the holes that get vibe-coded apps in trouble first.

Find your open doors

Paste your URL and Blinkof checks all five — and a lot more — for free.

Run a free blink test →