Supabase Row Level Security in plain English
What RLS is, why a Supabase table with it switched off is open to the whole internet, and the exact steps to lock yours down.
If your app uses Supabase, the most important security setting you have is called Row Level Security, or RLS. Many AI-built apps ship with it off.
What RLS does
Your app talks to Supabase straight from the browser, using a public key (the anon key). That key is visible to everyone, and that is fine, because it is supposed to be weak. What makes it weak is RLS.
Think of each table as a filing cabinet. With RLS on and no rules, the cabinet is locked. You then add rules called policies, such as “a signed-in user can read only their own rows”. With RLS off, the cabinet is open: the public key can read, and often change, every row.
How AI tools get this wrong
When a tool creates a table for you, it may skip RLS to make the demo work. Or it turns RLS on and adds a policy like using (true), which means “everyone can do everything”. Both leave your users’ data open.
How to check
In the Supabase dashboard, open Table Editor. A table with RLS off shows an “RLS disabled” badge. You can also run this in the SQL editor to list tables without RLS:
select tablename from pg_tables
where schemaname = 'public' and rowsecurity = false;
Greenlight Scan checks this from the outside, the same way an attacker would: it uses your public key and asks each table how many rows it can see. It only asks for a count and never downloads the rows.
How to fix it
Turn RLS on for each table:
alter table public.profiles enable row level security;
Then add a policy. For a table where each row belongs to one user:
create policy "own rows" on public.profiles
for select using (auth.uid() = id);
create policy "update own row" on public.profiles
for update using (auth.uid() = id);
Test it while signed out and while signed in as a different user. If you can still see someone else’s row, the policy is too wide.
Things to watch for
- Policies with
using (true)are the same as no protection. - Storage buckets have their own policies. A bucket that can be listed publicly exposes every file name.
- Never use the
service_rolekey in the browser. It ignores RLS completely.
You can ask your AI tool: “Enable Row Level Security on every table in the public schema and write policies so users can only access their own rows. Do not use policies that return true for everyone.”
Check your own app in about 2 minutes.
Scan my app freeThe Friday leak report
One short email a week: the newest ways AI-built apps leak data, and the one-line fix for each. No spam, unsubscribe any time.