Supabase · row-level security
Supabase RLS: how to tell if it is off
Row-level security is set table by table, so "is RLS on?" has one answer per table, not one per project. First, see whether your live app talks to Supabase from the browser at all — then the three places it goes wrong:
✓ Passive check · reads only what your app already sends every visitor · nothing is stored
1 · what goes wrong
Off on a table
Supabase's dashboard marks a table without row-level security as unrestricted, and the Security Advisor lists it under "RLS disabled in public". Tables created in the dashboard's table editor get it switched on by default. Tables created with SQL — in a migration, or by an AI agent following a prompt — do not, unless the SQL says so.
The table answers anyone holding the public key in your page, signed in or not: every row, through the same API your app uses.
2 · what goes wrong
On, but admitting everyone
A policy written as using (true) switches row-level security on and then lets every row through. It passes the dashboard's badge and the advisor's "RLS disabled" check, because RLS is not disabled.
The same exposure as no RLS at all, with a green light on it. This is the one people miss.
3 · what goes wrong
On, but checking the wrong thing
A policy that compares a column the browser can set — a user_id sent in the request, a role stored in a profile row the user can edit — looks correct and is not.
One customer edits one value and reads, or changes, another customer's data.
Questions people ask
Is RLS on by default in Supabase?
For tables created in the dashboard's table editor, yes. For tables created with SQL, no: row-level security has to be enabled in the same statement or migration, and policies written for it.
Can you see my RLS settings from outside?
No. A passive check of your address can see that your app talks to Supabase from the browser, and whether a secret key is in the JavaScript. Which tables have row-level security in force, and what the policies admit, is read from your code and migrations by the full check.
RLS is on and Supabase shows no warnings. Am I safe?
Not necessarily. A policy that admits every row, or trusts a value the browser sends, raises no warning. Whether each policy matches who should see what is a question about your app's rules, not about a switch.
An address shows only what a visitor sees. Row-level security policies, backups, tests and secrets with fallback defaults are in your code: the full check reads 118 of them inside Claude Code, Cursor or Codex, free. The full check, in your coding tool →
When you want the gaps closed the way serious software teams close them, the same prodready connection runs the SDLC on your project.