← Supabase RLS exposure checker
The Supabase dashboard already gives you two ways to look at RLS: Table Editor, which browses your table data, and the Advisor, which lints your project's configuration and flags a table with RLS switched off. Both are useful, and both answer a different question than the one this checker answers.
This checker sends one capped, read-only GET per table, using the anon key you provide, and reports which tables actually return real rows to that unauthenticated request -- the same request any visitor's browser (or curl) can already send. It does not read your policies, your RLS toggle state, or anything in the dashboard; it only reports what the anon key's own request actually got back.
| What you are trying to find out | Where to look |
|---|---|
| Is there any table in this project with RLS switched off entirely? | Either -- Advisor's lint catches this at a glance if you are logged in, and so does this checker. |
| Does a table with RLS enabled still return real rows to the anon key, because its policy is broader than intended? | This checker. Advisor's lint is a binary off/on read of the RLS toggle -- it does not evaluate what an enabled policy's USING clause actually returns. |
| If I open Table Editor and see data, does that mean the anon key can read it too? | No, and neither view answers this on its own. Table Editor runs as your own project session and shows you the data regardless of RLS. This checker sends the anon-key request itself and reports the real response. |
| Is a table returning zero rows because RLS is correctly blocking the anon key, or because the table is simply empty? | This checker's unconfirmed category names that ambiguity explicitly rather than guessing. Neither dashboard view distinguishes the two either, since both show you the table's real, unfiltered state as its owner. |
| Can I run this without a dashboard login, project-member access, or a service-role key? | This checker, and its CLI -- the anon key is the only credential it uses, the same one your own app's client already holds. |
| Can I gate a deploy on this in CI, unattended, without storing a dashboard session anywhere? | This checker's CLI -- exit code 1 on any exposed table. |
These are not a replacement for each other. Advisor is worth reading regularly as a configuration lint, and Table Editor is how you manage your own data day to day. This checker fills the gap between them: what the anon key's own request actually returns, checked the same way after every deploy rather than only when someone remembers to look.
No. Table Editor runs as your own logged-in project session, which is built to show you your data for management regardless of what RLS would do to an outside request -- that is the whole point of an admin data browser. Seeing rows there tells you the data exists; it tells you nothing about what an unauthenticated anon-key request actually receives. This checker sends that exact request -- the same one any visitor's browser can send -- and reports the real response.
It flags a table where RLS is switched off entirely, and it is a genuinely useful lint -- but that binary check does not evaluate what an enabled policy's USING clause actually returns. A table can have RLS turned on and still hand the anon role every row, if the policy attached to it is broader than intended (a common shape when a policy is copied from another table, or written as a quick USING (true) during development and never tightened). Advisor's lint reads as clean on that table; this checker does not read the policy at all -- it sends the request and reports what came back.
Neither the dashboard's own views nor a policy read-through resolves this on their own -- an empty table and a table RLS is correctly blocking look identical from the anon key's side: zero rows, no error. This checker reports that case as its own category, unconfirmed, rather than guessing either way, and names the one way to resolve it: insert one throwaway test row and re-run, or check the row count from the dashboard directly as the table owner.
Table Editor and Advisor both need a project member session -- they are dashboard features. This checker, and its CLI, need only what your own app's client already has: the project URL and the anon key. No account, no login, and the CLI's exit code 1 on any exposed table means it can gate a CI pipeline unattended without holding a dashboard session or a service-role key.