Supabase: row-level security and API keys
Many AI app builders (including Lovable and Bolt) use Supabase or a Supabase-style Postgres database. If you only fix one thing before launch, make it this.
1. Understand the two kinds of keys
Supabase gives you a public key that is meant to be in your browser code (the anon / publishable key), and a secret key (service_role / secret key) that bypasses access rules entirely. The public key isn't a secret. Your security comes from your access rules, not from hiding that key. The secret key must never appear in frontend code, a public repo, or a prompt you share. (Supabase: API keys)
- Search your project for
service_role,sb_secret_and any key you pasted into chat. None should be in client-side files. - If a secret key was ever exposed, rotate it in the Supabase dashboard.
2. Turn on row-level security (RLS) for every table
RLS is a Postgres feature that decides, row by row, who can read or change data. With RLS enabled and no policies, nobody can access the table through the public API. Policies then open up exactly what each user should see. (Supabase: Row Level Security)
-- Enable RLS
alter table public.notes enable row level security;
-- Each signed-in user can read only their own notes
create policy "read own notes" on public.notes
for select to authenticated
using ( (select auth.uid()) = user_id );
-- ...and insert only rows that belong to them
create policy "insert own notes" on public.notes
for insert to authenticated
with check ( (select auth.uid()) = user_id );
- Every table in the
publicschema has RLS enabled. - No policy uses
using (true)on data that isn't meant to be public. - Update and delete policies exist only where users should be able to change data.
3. Test it like a stranger
Create two test accounts. Signed in as user A, try to read, change, or delete user B's rows (for example by editing an ID in a request). Then try while signed out. You should get nothing back. Only test apps you own.
4. Run the Security Advisor
Supabase's database advisors flag common problems such as tables exposed without RLS. Run them before every launch. (Supabase: Database Advisors)
5. Don't forget storage and passwords
- Storage buckets also use access policies. Make sure private files are in private buckets with policies. (Supabase: Storage access control)
- Review password strength settings and leaked-password protection where your plan offers it. (Supabase: Password security)
Prompt you can give your AI builder
Enable row level security on every table in the public schema. For each table, write
policies so signed-in users can only select, insert, update and delete rows where
user_id = auth.uid(). Do not use the service role key anywhere in frontend code.
List every policy you created so I can review it.
Then check the policies yourself. An AI tool can get them wrong.