RLS and Supabase

1 min read

The anon key is public by design

Supabase's `anon` key is meant to live in the browser: it inevitably shows up in the JS bundle of any Supabase app. That is NOT a leak by itself, and detektd never flags it as a finding on its own.

RLS is the real barrier

What actually protects your data is Row Level Security (RLS) on each table, not the anon key's secrecy. A table with RLS disabled, or a policy that allows `select`/`insert`/`delete` without filtering by owner, is readable and writable by anyone holding the anon key, which is to say, any visitor to your site.

What a correct policy looks like

Enable RLS on every table, then write policies that explicitly filter by owner (typically `auth.uid() = user_id`) instead of granting broad access "to make it work" (`using (true)`).

sql
-- 1. turn RLS on for the table
alter table public.orders enable row level security;

-- 2. a row is only visible to the user who owns it
create policy "select own orders"
  on public.orders for select
  using (auth.uid() = user_id);

-- 3. same for writes, never just "using (true)"
create policy "insert own orders"
  on public.orders for insert
  with check (auth.uid() = user_id);

The fix attached to each RLS finding includes a policy example tailored to the exact table involved in your own schema, not this generic example.

Was this article helpful?