Vibe Coding Security Checklist: How to Secure Your AI-Built App Before Launch
Published October 17, 2026
AI tools like Cursor, Claude Code, Lovable, Bolt, and Replit can build a working app in an afternoon. They're less reliable at the boring parts that keep it safe: keeping keys secret, locking down the database, checking who's allowed to do what, and stopping one visitor from running up your bill.
This checklist walks through the most common security mistakes in vibe-coded apps, in plain English. Work through it before you share your link. It helps you catch common mistakes, but no checklist can promise your app is 100% secure, and your AI can be wrong too. If your app handles payments, health data, or other sensitive information, get a human security review as well.
Golden rule: don't accept "done" or "it's secure" from your AI. Ask it to show you the exact file, line, setting, or policy it checked, and how you can check it yourself.
1. Find every secret in your project
Search your whole project (config files, scripts, old files) for API keys, passwords, tokens, and database connection strings.
Sort each one: meant to be public (a Supabase publishable key, called the anon key on older projects, or a Firebase web config) or must stay secret (an OpenAI key, a Stripe secret key, a Supabase secret key, called service_role on older projects).
Check which values reach the browser. Prefixes like NEXT_PUBLIC_ in Next.js or VITE_ in Vite send a variable to the front end, so a secret key must never use them.
Make sure .env files are listed in .gitignore, and keep a .env.example with names but no values.
Never paste real secret values into an AI chat. Use the variable name instead.
2. Move paid API calls to the server
A key in browser code is visible to anyone who opens DevTools, even if it came from an environment variable.
If the browser calls a paid service such as OpenAI directly, move that call into a server route, server action, or serverless function (on Supabase, an Edge Function).
Have the route check that the user is logged in and validate the input before calling the service.
Return only what the front end needs, never the key or raw error details.
If a secret key was ever in browser code on a live site, rotate it. Someone may already have copied it.
3. Check your Git history, not just your code
Deleting a key from your code doesn't remove it from old commits.
Scan your full history with a well-known free scanner such as gitleaks or trufflehog.
On GitHub, secret scanning runs free and automatically on public repos, and push protection for personal accounts blocks known secret types in pushes to public repos by default. Private personal repos usually aren't covered, so a local scan still matters.
If a real key turns up: rotate it at the provider first, then think about cleaning history.
4. Lock down Supabase with Row Level Security (RLS)
Supabase's publishable key is public by design, so Row Level Security is what stops one user from reading another user's rows.
Check RLS table by table. Tables created in the Supabase Table Editor get RLS turned on automatically, but tables created with SQL, including by an AI tool or a migration, don't unless the SQL turns it on.
Flag any table with RLS off, any policy that allows everyone with true, and any table with RLS on but no policies (which blocks all access).
Write separate policies for select, insert, update, and delete, using auth.uid() to match rows to the logged-in user.
Check table grants too. RLS decides which rows a role can reach; grants decide whether the anon and authenticated roles can act on the table at all.
Run Supabase's Security Advisor (or supabase db advisors in the CLI) and fix what it flags.
Test as two real users. The SQL editor runs as an admin role and skips RLS, so a query working there proves nothing.
Never "fix" an access error by putting the secret (or legacy service_role) key in your app.
Using Firebase? Review your security rules the same way. Firebase App Check adds a layer on top of rules and blocks some abuse, but it doesn't replace them.
5. Try to see someone else's data
Create two test accounts. Logged in as User B, try to open User A's pages, records, and API routes by changing IDs in the URL or request.
Log out and try again.
Make sure admin pages and roles are checked on the server, not just hidden in the UI.
6. Validate input and verify webhooks
Validate everything users send on the server: type, length, and format.
Ask your AI to check for common web attacks like cross-site scripting (XSS) and injection, and explain each finding in plain words.
If you take payments with Stripe or receive other webhooks, verify the webhook signature before trusting the event.
7. Cap costs and stop abuse
Turn on a hard monthly limit, not just an alert, with your AI provider. OpenAI, Anthropic, and Google's Gemini API all offer limits that can stop requests, though some spend can still get through after the limit is reached.
Add rate limits to your routes, plus per-user daily limits on AI features.
Protect sign-up and contact forms from bots.
8. Check your packages
Confirm every package your AI added actually exists and is the one you meant. AI tools sometimes suggest package names that don't exist or look like real ones.
Turn on dependency alerts (on GitHub, Dependabot alerts) and review outdated or vulnerable packages.
9. Run a pre-launch review and make it prove it
Before you share your link, ask your AI for a security-only review that ends with a list of issues ranked by severity.
For each fix, make it show what changed and how you can test it yourself.
Keep logs and error messages free of secrets and personal data.
Fix one thing at a time and commit after each fix, so a security fix that breaks a feature is easy to spot.
If you've already leaked a key
Act fast, in the right order: rotate the key at the provider, update your host's environment variables and redeploy, check usage and billing for activity you didn't cause, and only then clean the key out of your code and Git history. The free prompt below walks you through it.
Free sample prompt: I Leaked an API Key: What Do I Do Right Now?
From Ship It Safe, Section 8 (Prompt 8.1). Copy it, fill in the brackets, and paste it into your AI tool. Don't include the key itself.
8.1 I Leaked an API Key: What Do I Do Right Now?
Use this when a key was committed to Git, shown in browser code, pasted somewhere public, or flagged by a scanner or provider email. You get a calm, ordered checklist for a leaked key.
Fill in: [WHICH KEY] (e.g. "OpenAI API key", "Supabase secret key", "Stripe secret key"), [WHERE IT WAS EXPOSED] (e.g. "public GitHub repo", "front-end code on my live site", "posted in a chat"), [TIME], [HOST].
I think I leaked a secret and I need step-by-step help, in the right order. Keep it calm and simple.
Which key: [WHICH KEY] (don't include the value)
Where it was exposed: [WHERE IT WAS EXPOSED]
For roughly how long: [TIME]
Where the app is deployed: [HOST]
Please give me:
1. Step 1, right now: how to revoke or rotate this specific key at the provider and create a new one. Tell me where to find this in the provider's dashboard (if you're unsure of the current layout, say so and point me to the docs).
2. How to put the new key into my host's environment variables and redeploy, so the app keeps working.
3. How to check the provider's usage, logs, or billing for activity I didn't cause.
4. Only after rotating: how to remove the key from my code and, if needed, Git history (and why rotating matters more than cleaning history).
5. Whether I should contact the provider's support (for example, about unexpected charges).
6. How to stop this from happening again (secret scanning, pre-commit hooks, server-only keys).
Tips to customize: If the leaked key is a database admin key (like a Supabase secret key or legacy service_role key), also review your data for unexpected changes and see Prompt 8.2 in Ship It Safe.
FAQ
How do I secure a vibe-coded app before launch?
Start with five checks: find exposed secrets, scan your Git history for old keys, confirm Row Level Security or security rules on every table, try to read another user's data with a second test account, and set a hard spending limit with your AI provider. Then run a full pre-launch security review and make your AI show proof for every fix.
What is Supabase RLS, and why do vibe coders need it?
Row Level Security is a Postgres feature that decides which rows each user can read or change. Supabase's publishable key (anon key on older projects) is public by design, so RLS is what stops strangers from reading your data. Tables made with SQL, including by AI tools, don't get RLS automatically, so check every table.
I deleted an exposed API key from my code. Am I safe?
No. The key can still sit in your Git history, and anyone who saw it may have copied it. Rotate or revoke it at the provider first, update your environment variables and redeploy, check usage for activity you didn't cause, then clean up your code and history.
Is a Supabase publishable or anon key safe to put in the browser?
Yes, it's meant to be public, but only if RLS is on and your policies are correct. The secret key (service_role on older projects) bypasses RLS and must stay on the server only.
Can AI prompts make my app 100% secure?
No. Prompts help your AI catch and fix common mistakes, and your AI can still be wrong. If your app handles payments, health data, or other sensitive information, get a human security review too.
Which AI coding tools do the Ship It Safe prompts work with?
They're plain-text prompts, so they work with Cursor, Claude Code, Claude, ChatGPT, Windsurf, Lovable, Bolt, Replit, and any other AI tool that accepts a prompt. The pack covers Supabase and Firebase databases specifically.
Prompt pack
Get the full checklist as 24 copy-and-paste prompts
Ship It Safe: Lock down your vibe-coded app before launch. 24 prompts in 8 sections: secrets and API keys, Supabase and Firebase security, login hardening, bad input and web attacks, cost and abuse limits, packages, pre-launch "prove it's done" checks, and what to do if you've leaked something. Includes a 30-minute quick start.
$15
Works best with
Cursor or Claude Code: the audits search your whole project and run scanners and audit commands, which these agents can do.
Lovable: its backend runs on Supabase, or you can connect your own Supabase project, so the RLS prompts apply directly.
ChatGPT or Claude: fine for pasted rules, policies, or logs.