ShipShape

Guide

Supabase RLS check

Row level security decides which rows a role can touch after that role is allowed to touch the table at all. ShipShape Scan does not run this check. A public anon key is not evidence that RLS is on or off.

Grants first, then policies

Supabase’s Data API uses Postgres roles. A grant says the role may select or insert. A policy says which rows. If the grant is missing, PostgREST returns 42501 and the policy never runs. Supabase’s changelog states that split directly. From 30 October 2026, new tables in public on existing projects need the grant written down. See the 30 October explainer and the changelog entry.

RLS is documented in Row Level Security. Enabling it without a policy denies rows to anon and authenticated. service_role bypasses RLS, which is why that key does not belong in the browser.

What to look at in the dashboard

Open the table in the Supabase Table Editor. The RLS badge should say enabled, not disabled.

Open Authentication policies for that table. A policy with using (true) for anon is a public table, even with RLS “on”. A policy that compares auth.uid() to a user column is the usual shape for private rows.

In the SQL editor, select relname, relrowsecurity from pg_class for your schema lists which tables have RLS enabled. That query is yours to run. This site never connects to your database.

alter table public.your_table enable row level security;

create policy "read own rows"
on public.your_table
for select
to authenticated
using (auth.uid() = user_id);

What a ShipShape scan can add

If the published page contains a Supabase project URL or an anon key, the Quick Check reports it as client config. That is expected for a browser app. If it contains a service_role key, the finding is critical and the key should be rotated. The Launch Report includes the SQL above, plus the grants the October change requires. Pasting that SQL is still your step. The scan cannot see policies, and paying for the report does not turn that on.

Run a free check