Security basics
The vibe coding security checklist, in nine checks
A vibe coding security checklist with nine items, each one something anyone can verify about your live app from outside, and each with a one-line test.

In short
- A vibe coding security checklist is only worth having if you can finish it. This one has nine items, because nine is how many things about a live app anyone can verify from outside it.
- Four of them decide whether a stranger can reach your data or your money. Run those four before you share the URL with anybody.
- The other five are settings and dates. They belong on the list, and none of them hands over a row of your database on its own.
You are about to send your app's address to somebody, and a small voice says you should check it first. So you search for a vibe coding security checklist and find one with twenty-five items on it, written by a person who assumes you already know what a Content Security Policy is.
Here is the part that list after list gets wrong: most of what is on them cannot be checked. "Use strong passwords" is advice. "Clean up dead code" is housekeeping. "Follow the principle of least privilege" is a sentence. None of them has a test, so none of them can be finished, and a list you cannot finish is a worry with numbers on it.
This one has nine items. Nine is how many things about a live app anybody can verify from outside it, without your password, your repository or your Supabase account. Each one has a test you can run yourself and each test comes back yes or no.
Think of it as the walk a pilot does around an aircraft before a flight. It is short, everything on it is visible from the tarmac, and it replaces nothing in the maintenance log. The last section of this post is about the log.
What should be on a vibe coding security checklist?
Nine questions, and they are the nine a stranger could ask about your app this afternoon whether you checked or not.
| The check | The test you can run yourself | What it means if it comes back wrong |
|---|---|---|
| Secret keys in your code | Search the project for sk_, sb_secret_, service_role, AKIA | Whoever finds it can spend your money or read every row |
| Database rules | Supabase, then the Security Advisor | Anyone holding your public key can read those rows |
| Private files | Open /.env and /.git/config in a private window | Every key you thought was on the server is downloadable |
| Storage buckets | Supabase, then Storage, then the Public column and the policies | A stranger gets the list of what your users uploaded |
| Browser safety headers | A scan; there is no address-bar version of this one | Your visitors are easier to attack through your page |
| Published source maps | Browser developer tools, Sources, look for your own filenames | Your original code is readable, comments and all |
| Your own API addresses | Open one in a private window where you are not signed in | Whatever it hands back is public |
| Certificate expiry | Click the padlock, open the certificate, read "Valid until" | Visitors meet a full-page browser warning instead of a page |
| Domain renewal | Your registrar's expiry date, and whether auto-renew is on | The app disappears and the name goes on sale |
Our own free security scanner runs all nine on any live URL in about 20 seconds with no account, which is the fastest way to do the first pass. It reads, it never signs in, and it never writes anything. Every item below is still something you can check by hand, and the tests are written out so you can hold a line of our report against your own dashboard.
The four to run before you share the URL
Secret keys, database rules, private files and storage buckets. These four are where the thing exposed is your data or your money, and all four are yours to fix rather than your hosting platform's.
Three of them are the only checks in the whole set that can report a critical finding, and the fourth is the one where what is exposed is what your users uploaded. Between 12 and 14 August 2026 we ran all nine checks over 30,998 live vibe-coded apps, and the figures in each section below come from that run.
1. Is a secret key in the code your app ships?
Search your whole project for sk_, sb_secret_, service_role and AKIA. A
match inside anything the browser downloads is the finding.
Everything your app needs to run in a browser arrives in that browser, so a key
sitting in it arrives too. Some keys belong there: a Supabase anon or
sb_publishable_ key is an address rather than a permission, and finding one is
correct.
Which keys are safe in a frontend and which are not
is the whole of that distinction.
A secret key is the other kind. A Supabase sb_secret_ or service_role key
ignores every table rule you have ever written. A Stripe sk_live_ key moves
money. We found a key of that class on 52 apps out of 30,998, which is rare and
is the worst thing on this list when it happens. If yours is one of them,
rotate before you do anything else:
deleting the key from your code leaves the old value working.
2. Can a stranger read your database?
In Supabase, open the Security Advisor. Every entry saying a table is public but row level security has not been enabled is a table answering anyone who asks, and that exact warning has an article of its own.
Row Level Security is the rule that decides, row by row, who may see what. Without it, the publishable key sitting in your app is enough to read the table, and that key is in every visitor's browser by design.
This is the commonest serious finding in the whole set: 2,096 of the 3,680 apps whose Supabase project answered us, or 57%, had at least one table handing rows to a request with nobody signed in. Turning it on for every table is the fix. The advisor reads your settings rather than your database's answers, so finish by checking from outside: a table can have the setting on and a policy that lets everybody through anyway.
3. Can anyone download your private files?
Open yourapp.com/.env and yourapp.com/.git/config in a private window. Both
should fail to open.
An .env file is every key you believed was safely on the server, in a plain
list, at a guessable address. A .git directory is your project's history.
Neither is meant to be served, and both occasionally are, usually because a
build copied a folder it should not have.
This is the rarest thing we find: 8 apps out of 30,749. It is also five seconds of work to rule out, and it is where the most damaging leaks come from when it happens.
4. Will your storage buckets list what is in them?
In Supabase, open Storage. Read the Public column on each bucket, then open the policies on any bucket holding something that is not meant for everyone.
Two different things are going on here and they are easy to run together. A public bucket serves any file whose name somebody already knows. A listable bucket hands over the names, which turns "somebody would have to guess" into a directory of your users' uploads. Our check tests the second one, because that is the one that changes what a stranger can actually do.
792 apps out of 27,269 had a bucket that listed itself to us without a login. What a stranger gets from that list is the longer version, and the fix is usually one toggle plus one policy.
The five that can wait until you have users
Headers, source maps, your own API addresses, the certificate and the domain. Three of these are usually set by whoever hosts your app, and two of them are dates in a calendar.
None of them hands over a row of your database on its own, which is why they sit in the second group. One of the five is worth pulling forward if your app has a backend of its own, and it is flagged below.
5. Are the browser safety headers switched on?
This is the one item on the list with no version you can run from the address bar. A scan reads them, or you open your browser's developer tools, look at the Network tab, click the first request, and read the response headers.
They are small instructions to the browser: load this page over HTTPS only, refuse to be framed by another site, do not guess at file types. Their absence does not expose anything by itself. It removes protections that make other attacks harder.
Almost nobody passes this one and almost nobody can. 30,756 apps out of 30,981 were missing at least one, and on a builder subdomain the setting belongs to the platform. Whether you can do anything about yours depends entirely on where your app is hosted.
6. Is your original source code published?
Open your live app, open your browser's developer tools, and look at the Sources panel. If your own files are listed there with the code you wrote and the comments you left, the source maps went out with the build.
A source map is a translation table that turns the compressed file your app ships back into readable code. Developers use it to debug a live site. Published to the internet, it means anyone can read your app the way you wrote it.
3,885 apps out of 30,987 published theirs. It is not a leak by itself, and it becomes one when the code contains something you assumed nobody would read. What a published map exposes covers the difference and the build setting that turns it off.
7. Do your own API addresses answer a stranger?
Copy one of your app's own API addresses out of the Network tab, then open it in a private window where you are not signed in. Look at what comes back.
This is the item to pull forward if your app has a backend of its own, because anything an address hands to a request with no login is public, whatever the page in front of it looks like. 3,852 apps out of 30,926 had at least one.
The related setting is CORS, which decides which other websites may call your app from a visitor's browser. A wildcard there is often fine and occasionally is not, and which of the two you have is worth reading before you change anything.
8. Is your certificate about to expire?
Click the padlock in the address bar, open the certificate, and read the "Valid until" date.
Almost every host renews these automatically and almost every one of them works. 32 apps out of 30,851 had a certificate expired, expiring or untrusted. When it does fail, visitors get a full-page browser warning telling them your site is unsafe, and most of them leave.
9. Is your domain renewed?
Sign in to your registrar, read the expiry date, and check that auto-renew is on and the card behind it has not expired.
This is the least technical item on the list and the only one that can remove your app from the internet completely. 55 apps out of 30,980 had a domain expired or expiring. A lapsed name can also be registered by somebody else, along with every link anyone ever made to it.
What other checklists carry that is not a security check
Backups, error monitoring, dead code and password advice. The first of those is the one most likely to cost you something, and it is not a security check, because nothing outside your app can tell whether you have one.
That is the honest reason it is absent from the nine. A scanner reads your live site; a backup is a copy of your database sitting somewhere else, and no amount of looking at your app from outside can say whether it exists, whether it is current, or whether it would restore. It still belongs on your list. It belongs on the kind of list you keep rather than the kind you run.
Supabase's own backups depend on your plan and stay inside your Supabase account, which is fine until the problem is the account. The three routes to a copy you actually hold sets out what each one covers.
If you would rather it happened without you, that is what Reeve Care does. It takes a copy of your Supabase database on a schedule set by the plan you are on, every night on the entry tier and up to four times a day on the top one, reads each copy back before it counts as a backup, and keeps it somewhere Supabase cannot reach. How far back you can go is set the same way. Restoring is a button, and it takes a snapshot of the current state before it starts, so pressing it in a panic cannot destroy the thing you were trying to save. Uploaded files come too, once you connect a Storage credential, which is asked for separately because it is the one key we hold that can write: Supabase issues no read-only key for files. Care starts at $49 a month for one app, and that is a list price, so the pricing page is sometimes below the figure here and never above it. How a copy is taken, checked and put back is drawn step by step on the Supabase backups page.
The rest of what those lists carry is real work and not this work. Error monitoring tells you when your app breaks, which is operations. "Remove unused dependencies" is housekeeping. "Use strong passwords" is true of everything you have ever logged into.
How often should I run this again?
After every deploy that touched your database rules, your keys or your build settings. If that sounds like most deploys, it is, which is the real problem with a checklist you run once.
The walkaround happens before every flight for exactly this reason. Row Level Security gets switched off at midnight to make a page load and nobody switches it back. A key gets pasted into the frontend to ship a feature before a demo. A bucket gets opened for one upload and stays open. Every one of those is a normal Tuesday, and each is enough to turn a clean result into a serious one.
Reeve Monitor exists for that gap. It re-runs all nine checks every hour on up to three apps, watches whether the app is up every 60 seconds, tells you the day a result changes rather than waiting for you to look, and sends a monthly report in plain language. It is $12 a month at list, with seven days free before it charges you, and the pricing page is sometimes below the figure here and never above it. Monitor watches and nothing more. Backups are the Care plan above it, and Care holds a copy of a Supabase database only.
What none of this proves
That your app is secure. Nine checks coming back clean means nine questions asked from outside came back clean on the day you asked them.
Four things stay invisible to every item on this list, because none of them ever leaves your server. Your server code, including the database functions and edge functions nobody outside can read. The environment variables you kept out of the browser, which is exactly where they belong and also why a scan cannot confirm they are stored properly. Your version history, where a key you committed in March and removed in April is still sitting. And your app's own logic, such as whether one signed-in user can open another user's order by changing a number in the address.
What a URL scan can and cannot see goes through that boundary properly, including the three tools that read different things and where each one is blind.
What to do right now
What to do
- Run the four urgent ones in order: search your project for
sk_,sb_secret_,service_roleandAKIA; open Advisors, then Security, in Supabase; open/.envand/.git/configin a private window; read the Public column and the policies in Storage. - If you find a secret key, rotate it before you remove it. Deleting the key from your code leaves the old value working, and it is still in your version history and in anyone's cached copy of your site.
- Work the remaining five when nothing is on fire. Three of them belong to your host, and the two dates belong in your calendar.
- Put a backup somewhere your Supabase account cannot delete it, then restore it once so that you know it works.
- Run the whole list again after any deploy that touched your database, your keys or your build settings.
If your app keeps its data in Supabase, the version of all this written around that one stack is the Supabase apps guide. And if you want something to tick rather than to read, the 10-minute security checklist is the interactive one.
FAQ
What should I check before launching a vibe-coded app?
Four things, in this order: whether a secret key reached the code your app ships to browsers, whether your database tables answer a request with nobody signed in, whether files like /.env open straight from your live address, and whether your storage buckets will list what your users uploaded. Those four are where a stranger gets your data or your money. The other five items on the list are worth doing and none of them is a reason to delay a launch.
How long does this take?
Three of the four urgent ones are one look each once you know where to look: a search of your own project for four key prefixes, the Advisors page in Supabase, and two addresses typed into a private window. The database one takes as long as you have tables, because you read the policy on each. Our free scan runs all nine from outside in about 20 seconds with no account, which is the honest shortcut for a first pass.
Do I need a developer for any of it?
Not for the tests. Every one of the nine is a page in a dashboard, an address in your browser, or a search of your own project. Some of the fixes are a different matter: moving work that needed a secret key onto a server is real development, and writing a row-level security policy that lets the right people in is the part most owners hand to somebody. Running the tests yourself is still worth it, because what you find decides what you ask for.
What is the single most important one?
Whether your database tables answer a stranger. It is the one where the data at stake belongs to your users rather than to you, and it is the commonest serious finding we see. Of the apps whose Supabase project answered our scan between 12 and 14 August 2026, 57% had at least one table handing rows to a request with nobody signed in. A secret key in the bundle does more damage when it happens, and it happens far less often.
How often should I re-check?
After any deploy that touched your database rules, your keys or your build settings, and monthly otherwise. A result describes the app that was live when you asked. Row-level security gets switched off to make a page load and stays off, a key gets pasted in to ship a feature tonight, a bucket gets opened for one upload. None of those announces itself.
Does passing this mean my app is secure?
No. It means nine questions asked from outside came back clean on the day you asked them. An automated external check is not an audit, and the absence of a finding is not a guarantee. Everything running on your server is invisible to all nine: your server code, the keys you kept out of the browser, the key you committed in March and deleted in April, and whether one signed-in user can open another user's order by changing a number in the address.