I build multi-tenant systems on Next.js + Supabase, and I audit their RLS and grants.
I maintain a point-of-sale platform running in real shops — inventory with FIFO batches, recipe-based items, database-enforced staff permissions, thermal receipts, tax on the invoice. Around ninety migrations, real money moving through it every day.
Three security reviews on it turned up six real holes. Every one of them got past policies that were, as written, correct.
new column + SELECT -> denied until you grant
new column + UPDATE -> allowed until you revoke
That asymmetry is the one I would most like to have known a year earlier. It let the browser rewrite an invoice counter on a table whose reads I had locked down column by column.
supabase-rls-audit — one read-only SQL file. Paste it into the Supabase SQL editor, hit Run, read the counts. Ten checks, and every one of them is there because it caught a real bug in a production database.
Six ways I leaked data through correct RLS policies — the six holes, the fix for each, and how I proved each fix actually landed. Also بالعربي.
Authorization belongs in the database, not in the interface. Hiding a button is decoration, not security.
And nothing is confirmed by reading code. Every claim I make about a database, I make after asking that database as a real low-privilege user — the query and its response go in the report. After a revoke I ask it again:
select has_function_privilege('anon', 'public.my_func()', 'execute');"I ran the command" is not evidence.
I do full security passes on Supabase projects. Every finding proved by running the query as a real low-privilege user in your own project, ranked by what someone could actually do today, with the migration for each and a re-test showing it closed. Plus the checks that passed, so a future change that breaks one shows up as a regression.
Run the script yourself first. If it comes back all zeros, tell me and I will say so — I would rather lose the work than sell you a review you do not need.
If something comes back that you cannot explain, open an issue — I read them, and I am happy to look at the output with you.