Quick Answer
Before you ship a vibe-coded app, check six areas: secrets, authentication and authorization, data access rules, input handling, dependencies, and the live deployment. The 25 checks below take an afternoon by hand. Start with the four that do the most damage when missed: committed API keys, API routes that never check who owns a record, database tables without row-level security, and packages the AI invented.
Why AI-Built Apps Need Their Own Checklist
AI coding tools write code that works on the first demo, and that is the problem: working and safe are different tests. Veracode's 2026 GenAI Code Security Report puts the average security pass rate of AI-generated code at 56%. VibeDoctor's scans of 1,099 repositories through July 2026 found 35% had API keys or secrets committed, 4% imported a package that does not exist, and 6% had no rate limiting on auth endpoints. GitGuardian's State of Secrets Sprawl 2025 counted 23.8 million secrets leaked on public GitHub in 2024 alone.
The failures are predictable, which makes them checkable. Work through the list in order; the early sections are the ones attackers find first.
Secrets (Checks 1 to 5)
- No keys in source. Search for
sk_live,sk-,AKIA,service_roleandpassword =. Any hit in a file you commit is a leak. - No keys in git history. Deleting a key in a later commit does not remove it. Run
gitleaks detecton the full history, and rotate anything it finds. .envis ignored and not committed. Check.gitignoreand rungit ls-files | grep .env. See our guide on committed .env files.- No secrets behind public prefixes. Values prefixed
NEXT_PUBLIC_are inlined into the JavaScript sent to the browser (Next.js docs), andVITE_values end up in client-side code (Vite docs). Server keys must never use those prefixes. - Supabase service role key stays on the server. The anon key is designed to be public; the service role key bypasses row-level security entirely.
// BAD: the secret is bundled into client JavaScript
const openai = new OpenAI({ apiKey: process.env.NEXT_PUBLIC_OPENAI_KEY });
// GOOD: the key is read on the server, the browser calls your route
// app/api/chat/route.ts
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
Authentication and Data Access (Checks 6 to 11)
- Every API route checks the session. List your routes and confirm each one rejects anonymous requests unless it is meant to be public.
- Every query is scoped to the owner. Being logged in is not permission. A route that loads
/invoices/:idmust also check the invoice belongs to the caller. This is the bug behind the Lovable BOLA incident. - Row-level security is on for every Supabase table, with policies that reference
auth.uid(). Per Supabase's docs, a table in an exposed schema without RLS is readable and writable by any role with a grant on it, which can include the anon role behind your public key. More in our Supabase RLS guide. - Admin actions check a role on the server, not a flag the client sends or a hidden button.
- Login, signup and password reset are rate limited. Without it, credential stuffing is free.
- Session cookies are
httpOnly,SecureandSameSite.
Input and Output (Checks 12 to 15)
- Request bodies are validated with a schema (Zod, Valibot, Pydantic) before they touch the database.
- No string-built SQL. Look for template literals inside
query(),$queryRawUnsafeor.raw()calls. - No raw HTML from users. Search for
dangerouslySetInnerHTML,innerHTMLandv-html, and sanitize anything user-supplied. - File uploads check type and size on the server, and uploaded files are never executed or served from your app's own origin without checks.
Dependencies (Checks 16 to 19)
- Every imported package exists. AI assistants sometimes invent package names; attackers register them. Confirm unfamiliar names on npm or PyPI before installing. Background: hallucinated imports.
- No critical or high CVEs in the lockfile. Run
npm audit, Trivy or OSV-Scanner. - A lockfile is committed and versions are not
*orlatest. - Unused packages are removed. Every dependency is attack surface you did not write.
Payments and Webhooks (Checks 20 to 22)
- Webhook signatures are verified (Stripe's
constructEventwith your signing secret) before any handler runs. - Prices come from the server, never from an amount the client posts.
- Cancellations and failed payments are handled. A webhook that only handles success leaves cancelled users on a paid plan. See our Stripe integration guide.
The Live Site (Checks 23 to 25)
- Security headers are set: HSTS, Content-Security-Policy, X-Content-Type-Options, and a frame policy.
- HTTPS everywhere, a certificate that is not about to expire, and no mixed HTTP content.
- Nothing sensitive is publicly served: request
/.env,/.git/configand your source maps on the production domain and confirm each one returns 404.
How to Run the Checklist Without an Afternoon
Checks 1 to 5 and 16 to 19 are mechanical; Gitleaks (run it once over the full history for check 2), Trivy and a registry lookup answer them in minutes. Checks 6 to 15 need someone, or something, to read the code with the data model in mind. Checks 23 to 25 need a request against the real domain. If you would rather run all of it at once, VibeDoctor's Vibe Check (vibedoctor.io) scans your repository and your deployed URL together, covering committed secrets, dependency CVEs, hallucinated imports, unprotected routes, injection patterns, headers and SSL, and returns a ranked list with file paths and line numbers. Free to sign up.
Business logic stays yours: no scanner knows that a discount should never go negative or that a free user should not see the export button. Re-run the checklist after every large agent session, not just before launch. If you build in Claude Code, our guide to Claude Code security review covers what its built-in reviews catch, and our comparison of Snyk alternatives helps you pick a scanner.
FAQ
What is the most common security mistake in vibe-coded apps?
Committed secrets are one of the most common. In VibeDoctor's scans of 1,099 repositories, 35% had API keys or secrets in the repo, and a leaked key is among the fastest issues to exploit because bots scan public commits continuously.
Is Supabase safe to use with Lovable or Bolt?
Yes, if row-level security is enabled on every table with policies tied to the logged-in user. The anon key is public by design, so RLS is the main thing standing between your data and anyone who opens the browser console.
Do I need a security audit before launching an MVP?
You need the checks above, not necessarily a paid audit. A professional audit makes sense once you hold payment data, health data, or enterprise customers who ask for one.
How often should I run this checklist?
Before launch, after every large agent session, and whenever you add auth, payments or a new dependency. New CVEs publish against your existing lockfile even when you change nothing, so scan dependencies weekly.
Can I ask the AI to fix these issues itself?
Yes, and it usually does it well once it knows the exact file and line. The hard part is finding the issues, which is why a scan that reports locations is worth more than a prompt that says "make it secure".