Lovable + Supabase RLS Checklist Before You Launch
Updated 2026-10-17
Lovable apps typically talk to Supabase directly from the browser using the project URL and the public anon (publishable) key. That is a supported pattern — but only if Row Level Security (RLS) is enabled with correct policies on every table the anon role can reach. This checklist walks through what to verify before real users arrive.
Why RLS is the whole security model
The anon key is designed to be public. Anyone can copy it from your JavaScript bundle and call your Supabase REST endpoint directly, bypassing your UI entirely. What they can read or write is decided only by Postgres grants and RLS policies.
If a table in the exposed schema has RLS disabled, the anon and authenticated roles can usually read and modify every row in it. Supabase's dashboard warns about this, but generated projects can still ship with tables created later without policies.
Enable RLS and add owner policies
For a typical user-owned table, enable RLS and scope every operation to the signed-in user.
alter table public.notes enable row level security;
create policy "owners read" on public.notes
for select using (auth.uid() = user_id);
create policy "owners insert" on public.notes
for insert with check (auth.uid() = user_id);
create policy "owners update" on public.notes
for update using (auth.uid() = user_id) with check (auth.uid() = user_id);
create policy "owners delete" on public.notes
for delete using (auth.uid() = user_id);Test like an attacker (with your own project)
Open your browser devtools on your own app, copy the anon key, and query each table with curl. Every table should return only rows the policy allows — for an unauthenticated request that is usually nothing.
Repeat signed in as a second test user and confirm you cannot read the first user's rows.
curl "https://<project-ref>.supabase.co/rest/v1/notes?select=*" \
-H "apikey: <anon-key>" -H "Authorization: Bearer <anon-key>"Checklist
- RLS enabled on every table in the public schema
- Policies exist for select / insert / update / delete where needed
with checkclauses prevent writing rows for other users- No
using (true)policies on private data - Storage buckets private unless they must be public
- service_role key never appears in client code
- Internal tables moved to a non-exposed schema
Copy-paste fix prompt
Audit my Supabase schema: list every table in `public`, enable Row Level Security on each, and generate owner-scoped select/insert/update/delete policies using `auth.uid() = user_id`. Flag any table that has no user_id column so I can decide its policy manually.FAQ
Is it safe that my Supabase anon key is visible in the browser?
Yes, the anon/publishable key is meant to be public. Safety depends entirely on RLS policies and grants. The service_role or sb_secret_ key must never be public.
Can a passive scanner prove my RLS is broken?
No. A passive scanner can see whether your schema is enumerable and whether keys are exposed, but it does not read your rows, so it cannot confirm whether policies are effective. Test with the anon key against your own project.
Check your deployed app in ~25 seconds
Free passive scan: leaked keys, Supabase exposure, public config files and headers.
Run a free scan