Vibe-coded app security checklist: 12 things to check before you take money
You built it in a weekend, people signed up, someone wants to pay. Before they do, spend an hour on this list. None of it requires reading code. All of it has sunk a real app in the last year.
A note first: this is not an argument against vibe coding. You used the fastest tool there is to find out whether anyone cares, and you found out. "It works" and "it's secure" are simply different properties, and the model that wrote your app will tell you confidently that it has both. Check.
Secrets
Open your live app, press F12, look in Sources and Network for strings that start with
sk_, sk-, AIza or contain "secret". Anything you find is public. Anyone can run up your OpenAI or Stripe bill with it - people have woken up to five-figure invoices this way.Deleting a key from a file does not delete it from git history. If one was ever pushed, rotate it today.
Supabase's
service_role key and Firebase admin credentials bypass every rule. They belong on a server only.Who can see whose data
Create two test accounts. Log in as one, and try to request the other's data by changing an ID in the URL or in a request. If you can see it, so can everyone. This is the single most common finding in vibe-coded apps.
Type the admin URL while logged in as a normal user. A route that's merely not linked is not protected.
If you built your own login rather than using the platform's auth, ask the model to show you the table. If you can read a password, it's plaintext. Switch to the platform's auth or a proper library before anyone else signs up.
Money
Open the dev tools, find the element hiding the premium feature, delete it or change
display:none. If the feature now works, your subscription check lives in the front end. Real apps have been bypassed with two lines of CSS. The check - "does this user have an active subscription?" - must happen on the server, every request.Stripe, RevenueCat and the app stores send a signature with every event. If your code doesn't check it, anyone can send your server a fake "payment succeeded".
Test each one. The happy path was generated; the unhappy paths usually weren't.
Running it
If you've ever "tested something" and real users saw it, they do. Separate projects, separate keys, and a way to roll back a deploy.
Especially on anything that calls an LLM or sends email. Without it, one script turns your token bill into a security incident.
Default regions are often in the US. Analytics SDKs and AI calls send data to third parties. If your users are in Europe, you need to be able to answer this in one sentence - a corporate customer or a regulator will ask.
Stop taking new payments until they're fixed, then get a senior engineer to review the whole thing - most of these take an afternoon to find and days to fix, not a rewrite. We do this review in days and write down harden-or-rebuild, with reasons.
Vibe-coded → production →What you can't check from the outside
The list above catches the loud problems. The quiet ones - a database schema that will fall over at ten times the rows, a dependency with a known vulnerability, a background job that silently fails, the absence of any test that would catch a regression before a user does - need someone to read the code. That's a review, not a rebuild. Beware anyone whose first answer is "start from scratch, six months, six figures": what you built is a working specification that encodes every decision you made while talking to customers. Don't pay for the same app twice.
The last 20% isn't more prompting
Every founder who has vibe-coded a product knows the wall: each fix breaks something else, the app gets slower, and the model's confidence stays exactly where it was. That's not a prompting problem. It's the point where engineering starts - tests, structure, boring reliability. We ship with Claude Code on our own products and know precisely where the tools are brilliant and where they quietly lie. If you want a second pair of eyes, send the repo link and the one thing that scares you most on WhatsApp.