Supabase RLS policy examples (user owns row, and why using(true) is not a fix)
Copy-paste Supabase Row Level Security policies for the most common vibe-coded app patterns, plus how to test them.
Turning RLS on with no policies blocks every request from the anon and authenticated roles. That is safe but breaks the app, and the tempting AI fix is a policy with using (true), which lets everyone read everything again. Write policies that match who owns the data.
User owns the row
alter table public.notes enable row level security; create policy "read own notes" on public.notes for select to authenticated using ((select auth.uid()) = user_id); create policy "insert own notes" on public.notes for insert to authenticated with check ((select auth.uid()) = user_id); create policy "update own notes" on public.notes for update to authenticated using ((select auth.uid()) = user_id) with check ((select auth.uid()) = user_id); create policy "delete own notes" on public.notes for delete to authenticated using ((select auth.uid()) = user_id);
Public read, owner write
create policy "anyone can read posts" on public.posts for select using (published = true); create policy "authors write posts" on public.posts for all to authenticated using ((select auth.uid()) = author_id) with check ((select auth.uid()) = author_id);
Gotchas
- UPDATE needs both
using(which rows) andwith check(what the row may become), or users can reassignuser_id. - Don't trust user-editable metadata (
raw_user_meta_data) for roles; users can change it. - Views and security-definer functions can bypass RLS. Check them.
- Find unprotected tables:
select tablename from pg_tables where schemaname='public' and rowsecurity=false;
Test it
Sign in as user A and create a row. Sign in as user B in a private window and query that table with the anon key. You should get nothing back.
For every table in the Supabase public schema: enable RLS and write explicit policies per operation (select/insert/update/delete) scoped to auth.uid() ownership, with both USING and WITH CHECK on updates. Do not use using (true) except for intentionally public read data. List any views or security definer functions that bypass RLS.
Related: Enable RLS · Anon key explained
Scan your app free
Paste your URL. ShipLatch checks for leaked keys, exposed /.env and /.git, and flags Supabase/Firebase so you know what to lock down. The free scan finds the issues; the $29 Fix Pack gives you fix prompts written for your app and re-scans that prove each fix worked.
Want the whole pre-launch process in one place? Get App Security for Vibe Coders, our $9 PDF playbook.