Pre-Launch Security Checklist for Vibe-Coded Apps
AI tools are great at making an app work. They’re much less reliable at making it safe, because “safe” is mostly about what happens when someone uses your app in a way you didn’t plan for. Run this checklist before you post your link anywhere. Each item says what to check and why, and links to the official docs.
Honest limits: this list covers the most common, high-impact mistakes in AI-built apps. It isn’t a professional security audit. If your app handles health data, payments between users, children’s data or anything regulated, get a professional review too.
1. Secrets and API keys
- No secret has a browser prefix. Nothing secret starts with
VITE_orNEXT_PUBLIC_. Those values are copied into the JavaScript every visitor downloads. (Vite · Next.js) - Search your live bundle. Open your live site, then DevTools → Sources, and search for
sk_live,sk_test,rk_,sb_secret_,service_role,whsec_and your AI provider’s key prefix. You should find nothing. - Secrets live in the platform’s secret store, not in code: Lovable Cloud → Secrets, Replit Secrets, or Vercel Environment Variables. (Lovable · Replit · Vercel)
- No secrets in Git history. If one was ever committed, rotate it, even if you deleted the file later.
- Production uses live keys, previews use test keys. Stripe keeps sandbox and live keys separate (
sk_test_…vssk_live_…), and objects in one mode aren’t visible in the other. (Stripe: API keys) - Prefer restricted keys. Stripe recommends restricted API keys (
rk_…) with only the permissions your app needs, rather than an all-powerful secret key. (Stripe: API keys) - You redeployed after your last environment variable change. On Vercel, changes only apply to new deployments.
More detail: environment variables and API keys explained.
2. Database (Supabase / Lovable Cloud)
- RLS is enabled on every table in the
publicschema. A table without RLS is readable and writable by anyone with a grant on it. (Supabase: RLS) - Grants are set too, not just policies. Revoke the defaults from
anonandauthenticated, then grant back only what each role needs. - No
using ( true )on private data. That means “every row, for everyone the policy applies to”. - Permissions never come from
user_metadata. Users can edit it. Useapp_metadataor a roles table. - Views are created
with (security_invoker = true), or kept out of exposed schemas. - The Supabase secret key is server-only. It bypasses RLS completely. (Supabase: API keys)
- Security Advisor reviewed. Open it in the Supabase dashboard and read every finding. On Lovable, run the Quick scan (it opens with the Publish dialog) and a Deep scan from the Security view. (Lovable: Security)
New to this? Start with Supabase Row Level Security for beginners.
3. Sign-in and private pages
- Site URL points at production. In Supabase Auth’s URL Configuration, the Site URL is your real domain, not
http://localhost:3000. It’s used for confirmation and password-reset emails. (Supabase: Redirect URLs) - Redirect URLs are tight. Use exact paths for production. Keep
**wildcards for local dev and previews. - Private pages are protected on the server or by RLS, not just hidden in the menu. Hiding a button doesn’t stop someone calling the API directly.
- Admin features check a real role, not whether the user is signed in, and not something the browser sends.
- Leaked-password protection is on if you use email and password. On Lovable Cloud it’s Password HIBP check under More → Cloud → Users → Auth settings → Email. (Lovable: Security)
- OAuth callback URLs (Google, GitHub) include your production domain.
4. Payments (Stripe)
- “Paid” is decided by the server, never the browser. Landing on a
/successpage proves nothing. Anyone can type that URL. Unlock paid features only after your server receives a verified Stripe event such ascheckout.session.completed. (Stripe: After a payment link payment) - Webhook signatures are verified. Stripe signs every event in the
Stripe-Signatureheader. Verify it with the official library, using the raw request body and your endpoint’swhsec_…secret. Without verification, an attacker could send fake events to fulfil orders or grant access. (Stripe: Webhook endpoints) - Duplicate events are handled. Stripe may deliver the same event more than once, so log processed event IDs and skip repeats.
- Prices come from Stripe or your server, never from a value the browser sends.
- You ran a full test-mode purchase end to end, including a refund.
5. Basics that save you later
- Error messages don’t leak internals. No stack traces, SQL or keys shown to users.
- Forms validate input on the server, not only in the browser.
- Dependencies are up to date. Lovable’s Quick scan includes a dependency audit. Elsewhere, run
npm auditand read the results. - HTTPS works on every domain you use, including
www. - A privacy policy exists if you collect emails or any personal data.
6. The 15-minute “attack your own app” test
Do this in a private browser window, signed out, then again as a second test user.
- Signed out: open every private URL directly (dashboard, settings, admin). Each should redirect or refuse.
- Network tab: use the app normally and watch DevTools → Network. Look for any request or response containing a secret, or other users’ data.
- Swap an ID: if a URL or request contains an id (
/notes/123), change it to another user’s id. You should get nothing. - Replay as a stranger: copy a Supabase request (“Copy as cURL”) made as user A and run it signed in as user B. Private rows must not come back.
- Fake success: visit your payment success page without paying. Nothing paid should unlock.
- Paste a key into the search bar: search your live JavaScript one more time for
sk_,sb_secret_,service_roleandwhsec_.
If any of these fail, fix them before launch. Ask your AI tool to show its plan first and refuse any “fix” that disables RLS or moves a secret into the browser.
Go / no-go
Go when sections 1–4 are fully ticked and the six-step test passes. No-go if any secret is in the browser, any private table lacks RLS, or paid features unlock without a verified webhook. Those are the mistakes that turn a fun launch into a bad week.
Official sources used: Supabase: RLS · Supabase: API keys · Supabase: Redirect URLs · Lovable: Security · Stripe: API keys · Stripe: Webhook endpoints · Stripe: After a payment link payment · Vite · Next.js. Checked October 2026.
Want the whole launch path in one place?
The Ship It Kit bundles copy-paste prompts, step-by-step deploy guides and a pre-launch checklist for Lovable, Bolt, Cursor and Replit apps. One-time $19. Launch price: $19 $17 until November 14, 2026.