Auth and database
Enable Supabase RLS on every table
Why the Supabase anon key makes RLS mandatory, how to enable it with auth.uid() policies, and how to verify no table is open. Includes Firebase rules.
Why it matters
The Supabase anon key ships in your frontend by design. Without Row Level Security, anyone with that key can read, change and delete every row in tables exposed through the API.
How to fix it
- Enable RLS on every table in the
publicschema (and any other exposed schema). - Add policies that scope rows to the signed-in user with
auth.uid(). - Avoid
using (true)policies on anything that isn't genuinely public. - On Firebase, write Firestore and Storage security rules and never ship test-mode rules that allow all reads and writes.
alter table public.notes enable row level security;
create policy "own notes: read" on public.notes
for select using ((select auth.uid()) = user_id);
create policy "own notes: write" on public.notes
for insert with check ((select auth.uid()) = user_id);How to verify
- Open the Security Advisor in the Supabase dashboard; it flags tables with RLS disabled.
- Query a table with only the anon key and no session; you should get no private rows.
Questions
- Does enabling RLS with no policies break my app?
- Yes, it denies all access through the API until you add policies. That is the safe default.
- Does RLS apply to the service_role key?
- No. service_role bypasses RLS, so keep it on the server.
Related checks
- Keep the service_role key on the server
- Check permissions on the server
- Keep storage buckets private unless they must be public
Tick it off in the full checklist