RLS enabled is not RLS working
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 []
Get every Fix AI Slop Code episode
The code it wrote, the code it should have written and a check, for every episode
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.
Get this check as a script you can run tonight

The coding agent never holds production credentials
An agent with a production database URL will sooner or later run a migration or a cleanup against it, so production secrets never enter its env
Keys go in headers, never in URLs
A URL is written to server logs, CDN logs, browser history and error trackers, so an API key in a query string is a key in five places
Backups the app cannot reach, and one restore you have actually done
A backup on the same account the app or an agent can delete from is not a backup, and a restore you have never run is a number you do not have
If this check came back with more than you expected, that is worth a conversation