Database · 12 of 20

RLS enabled is not RLS working

Research, sourced
Check it
select tablename, rowsecurity from pg_tables where schemaname = 'public';select tablename, policyname, cmd, qual from pg_policies where qual = 'true';   -- the lock that locks nothingcurl -s "https://PROJECT.supabase.co/rest/v1/users?select=*" -H "apikey: PUBLISHABLE_KEY"   -- should be []
Free, no call

Get every Fix AI Slop Code episode

The code it wrote, the code it should have written and a check, for every episode

Free, straight to your inbox. No call, no pitch

Watch the video

Watch the episode

The same idea in a short video. It plays here, and nothing loads until you press play

What is going on

Row-level security is two things: a switch per table, and a policy per command. The switch alone blocks everything, which breaks the app, so the model adds a policy. The policy it adds is using (true), which allows everything. Green badge, every row readable. A view runs as its owner and bypasses RLS entirely unless security_invoker is on.

Where it bit

A June 2026 scan of 1,072 vibe-coded Supabase apps: 39 fully readable tables, 34 exposing emails, hashes or tokens, and 172 that allowed unauthenticated DELETE on tables named things like payments. A single Lovable education app: 18,000 users exposed.

The practice

One policy per command. Reads scoped to (select auth.uid()) = user_id. Inserts with with check. Roles from app_metadata or a roles table, never user_metadata, which the user edits from the browser. Read the Security Advisor before every deploy.

Free, no call

Get this check as a script you can run tonight

Free, straight to your inbox. No call, no pitch

What to do with this

If this check came back with more than you expected, that is worth a conversation

Book a free 30-minute call