It can be. Supabase's documentation says a table in an exposed schema without row level security is readable and writable by any role with a grant on it. Enable RLS on every table in an exposed schema, add policies, and revoke default grants to the anon and authenticated roles where they still exist.
The rule from the documentation
The Supabase guide on row level security states it in direct terms: a table in an exposed schema without RLS is readable and writable by any role with a grant on it. It then says to enable RLS on every table in an exposed schema.
It adds a second instruction that people miss. On projects that still grant the anon and authenticated roles by default, revoke those grants, because adding policies does not remove them.
That is the sentence to remember. A policy narrows access once RLS is on. A grant that is still in place on a table without RLS is the open door.
Why this matters for application developers
If your project exposes tables through its API, the browser can call that API directly. If a table is reachable that way and RLS is off, the database itself is the only access control, and the grants decide the outcome. Your front end code hiding a button does nothing, because anyone can call the API without your front end.
A table to audit against
| Check | What good looks like |
|---|---|
| RLS enabled on each table in an exposed schema | Yes, with no exceptions |
| Policies exist for each action you allow | Select, insert, update and delete are considered separately |
| Default grants to anon and authenticated | Revoked unless you have a specific reason |
| Tables that should never be reachable | Kept out of exposed schemas |
| Tests | Policies tested with each role, not assumed |
The guide points to a secure a table procedure covering grants, policies and testing, and mentions a test command for the database. Use the procedure for every table, not just the sensitive ones. A forgotten lookup table can still leak.
Steps
- List the schemas your API exposes.
- List every table in them and check whether RLS is on.
- For each table, decide who should read and write which rows.
- Write policies that express that, then test as an anonymous caller and as two different signed in users.
- Revoke grants that are broader than the policies need.
- Add a check to CI that fails when a new table appears in an exposed schema without RLS.
Step six is the one that holds over time. Tables are created in migrations, so the migration review is where the habit lives. Compare this with row level security basics and pitfalls in PostgreSQL and masking, RLS and column grants.
An AI tool and your database
If an AI assistant has access to your project database, the same rule applies to what it can read. See the Supabase MCP lethal trifecta for a related incident write up.
Safeguard scans dependencies, including database client libraries, and policy gates can hold a pull request when a check fails. A free scan is at gold.safeguard.sh/scan.
Try it yourself
Run the API scan and open a finding about an endpoint that returns data without checks. Look for how missing access control shows up from the outside.
Click through it at your own pace, or open it full screen.
Quick check
Do policies remove default grants?
No. The Supabase guide says adding policies does not remove them, so revoke the grants separately.
Which tables need RLS?
Every table in an exposed schema, according to the guide.
Is hiding a button in the UI enough?
No. The API can be called directly, so the database rules decide access.
Sources
Last reviewed: 19 October 2026.