Your app runs. You clicked through it, the sign-up works, the payment test went through. That is a good day, and it is not the same as being ready for strangers.
AI coding tools are very good at making something work and not very good at asking what happens when the wrong person uses it. Veracode's 2025 GenAI Code Security Report (80 coding tasks, 100+ models) found AI-generated code introduced security vulnerabilities in 45% of test cases. That is test cases, not apps and not all AI code. It is still a good reason to look before launch.
Trouble comes from three directions, and each one checks different things. An attacker looks for open doors. A regulator looks for missing notices and consent. A customer looks for the refund button and, when they cannot find it, calls their bank. This post covers five problems we see in AI-built apps, one or two from each direction, and a check for each that you can run in a few minutes with no tools beyond your own project.
Grey State Development makes LaunchVet, a pre-launch audit that runs inside Claude Code. It is mentioned near the end. You do not need it for anything below.
1. A secret key ships to every visitor's browser
Frameworks such as Next.js and Vite copy any environment variable with a public prefix (NEXT_PUBLIC_, VITE_) into the JavaScript every visitor downloads. AI tools sometimes put a secret key behind one of those prefixes to make a "client" call work. A Supabase service role key skips every database rule, so anyone who copies it can read and change everything. A paid AI provider key lets a stranger run up your bill.
Check it yourself:
grep -rniE "(NEXT_PUBLIC|VITE)_[A-Z_]*(SECRET|SERVICE|PRIVATE|KEY)" .env* src app lib
Anything that should stay private and appears in that list is a problem. A public Supabase anon key is meant to be public. A service role key, a Stripe secret key or an OpenAI key is not. Also confirm your .env files are ignored by git:
git check-ignore -v .env .env.local
If a secret has already been public, rotate it. Hiding it afterwards does not make it safe again.
2. The database is open to anyone holding your public key
With Supabase, the public anon key ships in your frontend by design. What stops visitors from reading every row is Row Level Security. AI tools often create tables without it, or switch it off to get past an error and never switch it back on.
Check it yourself, in the Supabase SQL editor:
select tablename, rowsecurity from pg_tables where schemaname = 'public';
Every table that holds user data should say true. Then look at the policies:
select tablename, policyname, qual from pg_policies where schemaname = 'public';
A policy whose condition is just true means everyone is allowed. Last, test it the way an outsider would: sign in as one test user and try to fetch a second test user's record by its id.
3. The payment webhook believes anyone who calls it
When Stripe finishes a payment it sends your server a message. If your handler does not verify the signature on that message, anyone can send a fake "payment completed" request and unlock the paid plan for free.
Check it yourself: open your webhook route and look for constructEvent (or your payment provider's equivalent) using the raw request body and the signature header. If the code parses the JSON body and acts on it straight away, that is the problem. Then send a made-up request:
curl -X POST https://your-app.example/api/webhooks/stripe -H "Content-Type: application/json" -d '{"type":"checkout.session.completed"}'
A safe handler answers with an error and does nothing. A handler that answers 200 and changes an account needs fixing before launch.
4. Tracking scripts fire before the visitor says yes
A cookie banner on the screen does not mean the scripts waited for the click. AI-generated layouts often load Google Analytics or a Meta Pixel on every page and add a banner that does nothing but sit there.
California Penal Code 637.2 lets a person injured by a violation sue for the greater of $5,000 per violation or three times actual damages, and actual damages need not be shown. Plaintiffs have sued sites over trackers under this law. Courts differ on how far it reaches, so read this as a reason to check, not a verdict.
Check it yourself: open a fresh private window, open your browser's developer tools, switch to the Network tab, then load your site and do not touch the banner. Look for requests to googletagmanager.com, google-analytics.com or connect.facebook.net. If they appear before you accept, the banner is not controlling them. The Accept and Reject buttons should also be equally easy to click.
5. Signing up is easy and cancelling is not
Sign-up that takes one click and cancellation that takes an email to an address nobody can find is how happy trials turn into disputes. Stripe says the card industry treats dispute activity above 0.75% as excessive, and a sudden spike can trigger monitoring earlier. For a small shop, a handful of disputes is a large percentage.
There can be a legal side too. California's amended Automatic Renewal Law (AB 2863, effective 1 July 2025) requires express consent to auto-renewal, an easy online cancellation path, and annual reminders. Other states have their own laws.
Check it yourself: subscribe with a test card, then try to cancel from your account page without help. Count the clicks. Then look for a refund policy and a support contact on your site, because both are what a confused customer looks for before they email you or dispute the charge.
How LaunchVet checks for these
LaunchVet runs inside your own Claude Code session, on your own repo. It reads the project and writes one file, launchvet-report.md, ranked from the worst finding down. Each finding names the file and line, explains why it matters, and includes a prompt you paste into Claude Code to fix it. It never edits your code. There is no LaunchVet server and no signup, and the scanner script makes no network calls. Claude Code itself still reads your files and talks to Anthropic the way it does for any task.
We ran it on a deliberately broken demo app built on Next.js, Supabase and Stripe. The report came back with 28 findings: 7 critical, 14 high, 6 medium and 1 low, and the verdict line "NOT READY TO LAUNCH: fix the critical findings first." All five problems above appear in that report, along with many more that this post does not cover. The ten we picked from that report, with the fix prompt for each, are in a separate write-up on dev.to: I ran a pre-launch audit on a deliberately broken vibe-coded app. You can also read the full demo report on GitHub.
A clean report means "no common issues found". It does not mean "safe". Checklists miss things, AI can make mistakes including in the report, and some items need a human to look at live settings: whether Row Level Security is switched on in the real database, what your payment dashboard is configured to do, and what spend limits your AI provider has set. If real money, health data or children are involved, a professional should look too.
Try it
The free core is open source (MIT) on GitHub and runs 26 checks. Pro is a one-time $19 on Gumroad and brings the total to 142 checks, with a payments and Stripe readiness module, an app store module, legal page starter templates and a CLAUDE.md security rulebook. You do not need Pro to fix what the free core finds.
- LaunchVet: what it does, how to install it, free versus Pro
- Free core on GitHub
- Pro on Gumroad: $12 with code LAUNCH12 until 2026-11-11 23:59 PT, then $19. 30-day refund.
LaunchVet is an automated checklist, not a security guarantee or legal advice. AI is used in this product and can make mistakes.