VibeHP guide · Updated Oct 2026

Supabase RLS check: is your database open to everyone?

Your Supabase anon key ships inside your frontend, so anyone can grab it. That's by design, and Row Level Security is the only thing between that key and your data. If a table has RLS off, or a policy says using (true), that table is effectively public.

We scanned 21 public vibe-coded apps: 57% had at least one Supabase policy open to everyone, 62% had committed a .env file, and 24% failed a clean npm install. The average launch health was 63/100.

01Find tables with RLS off

  • Run this in the Supabase SQL editor:
    select tablename from pg_tables
    where schemaname = 'public' and rowsecurity = false;
    Any row returned is a table the anon key can read and write freely.
  • Fix each one:
    alter table public.your_table enable row level security;
    With RLS on and no policies, nobody can access it via the API. Then add policies for what should be allowed.

02Find policies open to everyone

  • List them:
    select tablename, policyname, cmd, roles, qual, with_check
    from pg_policies where schemaname = 'public'
      and (qual = 'true' or with_check = 'true');
  • For each one, ask whether a logged-out stranger should be able to do this. Public product lists: fine. Profiles, orders, messages, payments: not fine.
  • Replace with an ownership check:
    drop policy "Anyone can read" on public.orders;
    create policy "Users read own orders" on public.orders
      for select using (auth.uid() = user_id);

03Check the things around RLS

  • The service_role key bypasses RLS entirely. Make sure it's only used in edge functions/servers, never in src/.
  • Views can bypass RLS. On Postgres 15+, create them with with (security_invoker = true).
  • security definer functions run with elevated rights, so check they validate auth.uid() themselves.
  • Storage: private buckets need policies on storage.objects too.

04Prove it

  • Open your app logged out, then in the browser console run supabase.from('orders').select('*'). You should get an empty result or an error.
  • Log in as user A and try to read user B's rows. It should fail.
  • Keep RLS in your migrations (supabase/migrations) so new environments are secure by default.
Shield icon

Don't want to check all this by hand?

Paste your GitHub link. VibeHP runs every check on this page (plus a git-history secret scan and a real build) and gives you an HP score out of 100, with a copy-paste AI prompt for every fix.

Check my HP for $19 →

One-time · Your code is deleted right after the scan

FAQ

What does using (true) mean in Supabase?+

It's a policy condition that's always true, so every request (including logged-out users with the anon key) passes. It's only appropriate for genuinely public data.

Is it safe to expose the Supabase anon key?+

Yes, if RLS is enabled with proper policies on every table. The anon key is meant to be public; RLS is what protects your data.

Does VibeHP check my live database?+

Not yet. VibeHP reads your migration files to find tables without RLS and always-true policies. Use the SQL on this page to confirm against your live project.