FixedLaunchBack

fix guide

Is my vibe-coded app secure? Seven checks before launch

·

All fix guides

Your app works, and you want to know if it is safe to put real users and their data in it. The builder wrote the code fast, and nobody reviewed it.

These seven checks cover the problems that are easiest to miss in an app on Supabase with a Vite or Next.js frontend. Most take a few minutes in the browser or the Supabase dashboard. They don't replace a full security review, but they catch the open doors.

1. See what a visitor's browser can see

Paste your live link into the free scan at fixedlaunch.com/scan. It lists what a visitor's browser can see, like leaked keys and exposed files, worst first.

The scan can't check database rules, sign-in, payments or background jobs. Steps 3 to 6 cover the first two by hand.

2. Secret keys in the frontend code

Vite's docs say variables prefixed with VITE_ are exposed in client-side source code after bundling, and that they should not contain sensitive information such as API keys. Next.js does the same with NEXT_PUBLIC_ variables.

Open your live site, press F12, open the Sources tab (Debugger in Firefox) and search all files for sk_, secret, service_role and the first few letters of each API key you use. Anything that shows up, a visitor can copy.

The Supabase publishable or anon key is meant to be public. A Stripe secret key, an OpenAI key or a Supabase secret key is not. Move those calls into server code, then delete the leaked key at the provider and make a new one.

signs The search finds a key that starts with sk_ or contains service_role in a file the browser downloaded.

3. Row Level Security on every table

Supabase's docs say the publishable key is safe to expose online, and that anyone can read it, so it only reaches what Row Level Security allows. That makes RLS the lock on your data. A table without it is open to anyone with the key.

Run this in the SQL Editor. Every table it lists has RLS off:

select tablename from pg_tables where schemaname = 'public' and rowsecurity = false;

Turn RLS on for each one and add the policies the app needs. Supabase RLS errors in AI-built apps, decoded shows what breaks when a policy is missing, so you can test right after.

signs The query returns table names.

4. Policies that let everyone read everything

RLS can be on and still open. A policy with using (true) for the anon role lets any visitor read every row. That is right for a public list of products. It is wrong for orders, messages or profiles.

Open each table's Policies page and read the rule in each one. Then test it: sign in as one user, copy the address of one of your records, and open it signed in as a second user in a private window.

signs A second user can see the first user's record, or a signed-out visitor can see private rows.

5. Storage buckets set to public

Supabase's docs say that with a public bucket, anyone who has the file's URL can access it. With a private bucket, every action goes through RLS policies.

Keep user uploads such as IDs, invoices and private photos in a private bucket, and show them with signed URLs that expire. A public bucket fits logos and images for public pages.

signs Users' private files sit in a bucket marked Public in the Storage dashboard.

6. Admin pages protected only by a hidden button

Generated apps often hide the admin link from normal users and stop there. The page and its data are still reachable by address.

Open /admin, or whatever your admin address is, in a private window while signed out. Then try it as a normal user. Both should be refused, and the data behind the page should be blocked by a policy or a server check, not only by the menu.

signs The admin page loads, or its data loads, for a signed-out visitor or a normal user.

7. The secret database key and old leaked keys

Supabase's docs say a secret key bypasses every Row Level Security policy you have, and should never go in a browser, a shipped application or source control. Search your repo for it as well as the live site.

If a key was ever committed to a public repo or pasted into a chat with a builder, treat it as leaked. Supabase's docs say to delete a leaked key right away.

If you think someone is already inside your app, that is an active incident. Contact your host and Supabase support first. I don't take active hacks.

signs Your repo history or an old chat contains a secret key.

Test it like a new user

  1. Run the scan again and check no secret key shows.
  2. Run the RLS query and check it returns no rows.
  3. Open another user's record as a second user and check it is refused.
  4. Open the admin address signed out and check it is refused.
  5. Open a private file's URL in a private window and check it doesn't load.

Common questions

Is it safe that my Supabase key is visible in my app's code?

The publishable or anon key is meant to be public, and it only reaches what Row Level Security allows. That is safe while RLS is on for every table with the right policies. The secret or service_role key is different: it bypasses every policy and must never reach the browser.

How do I check if my vibe-coded app leaks API keys?

Search your live site's code for your keys. Press F12 and search all files in the Sources tab for sk_, secret, service_role and the start of each key you use. Anything you find, a visitor can copy. Move those calls to server code and replace the leaked keys.

How do I find Supabase tables with Row Level Security turned off?

Run a query in the SQL Editor that lists tables in the public schema where rowsecurity is false. Turn RLS on for each one, add the select, insert, update and delete policies the app needs, then test as two different users.

Still stuck?

Not sure this is the cause? Paste your app's link into the free scan. It lists what a visitor's browser can see, like leaked keys and exposed files, worst first. The score is free; every fix as a prompt for your builder is $9, one-time.

Want a person to look inside? See the diagnosis

More fix guides

See all fix guides