Is My Vibe-Coded App Safe to Launch? A 15-Point Security Checklist
You built something real with Lovable, Bolt, Cursor, Claude, Grok or ChatGPT, and it works. The question that keeps people up the night before launch is whether it's safe.
AI coding tools are very good at making things work and not reliably good at making them secure. The gaps tend to be the same few things over and over: keys in the wrong place, databases left open, and dependencies nobody checked. The good news is that you can check most of them yourself in an afternoon.
Work through this list before you post your launch link.
Why this matters (real examples)
- Open Supabase databases. In May 2025, CVE-2025-48757 (CVSS 9.3, critical, as scored by MITRE; NVD has not published its own score, and Lovable disputes the CVE) documented Lovable-built apps where missing or weak Row Level Security let anyone with the public key read or write database tables. The researchers found 303 exposed endpoints across 170 Lovable projects, exposing data like user records and payment details.
- Leaked secrets at scale. GitGuardian's State of Secrets Sprawl 2025 found 23.8 million new secrets leaked in public GitHub commits in 2024, and that 4.6% of public repositories they scanned contained a secret.
- Poisoned packages. In September 2025, attackers hijacked 18 popular npm packages including
chalkanddebug, and the self-spreading Shai-Hulud worm then compromised more than 500 packages, according to CISA.
None of these needed a clever hacker. They needed one missed setting.
Section 1: Secrets and keys
☐ 1. No secret keys in frontend code.
Search your code for VITE_, NEXT_PUBLIC_ and PUBLIC_ variables. Anything with those prefixes is shipped to every visitor's browser. OpenAI keys, Stripe secret keys (sk_live_) and Supabase service_role keys must never have them.
☐ 2. No secrets in your git history. Deleting a key from today's code doesn't remove it from earlier commits. Scan your history, not just your current files.
☐ 3. .env is gitignored and not tracked.
Your .gitignore should include .env, .env.local and .env.*.local. Run git ls-files | grep .env. The only result should be .env.example, if you have one.
☐ 4. Any key that ever leaked has been rotated. If a key was ever public, even for an hour, replace it at the provider. Removing it from the code is not enough.
Section 2: Database (Supabase)
☐ 5. Row Level Security is on for every table. In the Supabase SQL editor:
SELECT tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';
Every row should say true. Tables created with SQL or migrations, which AI tools often generate, don't always get RLS switched on.
☐ 6. Policies actually restrict access.
RLS with a USING (true) policy is an open door with a sign on it. Policies should usually check ownership, for example auth.uid() = user_id.
☐ 7. You've tested as a stranger. Query your tables with just the anon key and no login. You should get nothing private back. Then log in as user A and try to read user B's data.
☐ 8. Storage buckets are private unless they need to be public. Check each bucket's settings, especially ones holding user uploads.
Section 3: Auth and permissions
☐ 9. Admin features are checked on the server. Hiding an "Admin" button in the UI isn't security. The database policy or server function must check the user's role.
☐ 10. Server endpoints require login. Any Edge Function or API route that costs money (AI calls) or changes data should verify the user and apply rate limits.
Section 4: Payments
☐ 11. Prices are set on the server. Create Stripe Checkout Sessions on the server using price IDs you control. Never trust an amount sent from the browser.
☐ 12. Access is granted from webhooks, not redirect pages.
Anyone can visit /success. Unlock paid features only after a verified Stripe webhook (check the signature with your webhook secret).
Section 5: Dependencies
☐ 13. No known-vulnerable packages.
Run npm audit (or pnpm audit / yarn npm audit) and fix high and critical issues, especially in packages that run in production.
☐ 14. A lockfile is committed.
package-lock.json, pnpm-lock.yaml or yarn.lock pins exact versions, so a surprise malicious release doesn't sneak into your next build.
Section 6: Basics you'll be glad you did
☐ 15. You can recover and you can be reached.
- Database backups are enabled, and you know how to restore one.
- Spend limits and billing alerts are set on AI providers and hosting.
- You have a privacy policy if you collect personal data, plus a contact email for security reports.
A paste-ready prompt for your AI tool
Use this as a first pass, then check its work against the list above:
"Audit this project for launch security. List (1) any secret keys reachable from frontend code or VITE_/NEXT_PUBLIC_ variables, (2) every Supabase table and whether RLS is enabled with owner-scoped policies, (3) any admin or paid feature enforced only in the UI, (4) any Stripe amount taken from the client, and (5) server endpoints without auth or rate limiting. Don't change code yet. Give me the list with file paths."
Asking for a list first, rather than letting it "fix everything", keeps the AI from making silent changes you can't review.
What a scanner can and can't tell you
Some items on this list, like RLS policies, webhook logic and admin checks, depend on your app's live configuration and need hands-on testing. Others can be checked automatically from your code, quickly and reliably:
- secrets in current files and git history
.envand.gitignoremistakes- vulnerable npm, pnpm, yarn and Python packages
Get your launch score
Run a free ShipCheck scan on your GitHub repo (public, or private via Connect GitHub) before you launch. It runs gitleaks across your files and last 100 commits, checks your packages against the OSV vulnerability database with osv-scanner, and flags .env/.gitignore problems. You get a 0–100 score in plain English, which checks for leaked secrets in your files and recent history (items 1–2), committed .env files and .gitignore gaps (item 3), and known-vulnerable dependencies and missing lockfiles (items 13–14), usually in under a minute. It can't see which variables your bundler exposes or test your live configuration, so the rest of the list is still on you.
Built it with Lovable, Bolt, Cursor, Claude, Grok or ChatGPT? Is your repo safe to ship?
Paste a public GitHub repo, or connect GitHub for a private one, and get a risk score in under a minute. Free.
Built it with Lovable, Bolt, Cursor, Claude, Grok or ChatGPT? Is your repo safe to ship?
Paste a public GitHub repo, or connect GitHub for a private one, and get a risk score in under a minute. Free.