One SQL file. Paste it into the Supabase SQL Editor, hit Run, get a list of the

things that are about to bite you — worst first.

No install, no npm package, no connection string handed to a stranger, no

account anywhere. It only SELECTs from system catalogs: it reads none of your

table data, writes nothing, and sends nothing anywhere. It is one file so that

you can read it before you run it.

curl -O https://raw.githubusercontent.com/Concepto505/supabase-audit/main/audit.sql

What the output looks like

Illustrative — table names invented, shape is real:

Nothing came back? Then these eleven failure modes are not present. That is a

useful answer too.

Two of these deserve a note

#4 is the one that surprises people. In Postgres, a newly created function

is executable by PUBLIC unless you say otherwise. On Supabase that means the

anon key can call it. The REVOKE has to live in the same migration that

creates the function, or there is a window where it is open.

#6 is not automatically a bug. A view without security_invoker runs with

its owner's rights, which is exactly right when the view already filters by

auth.uid() itself. Read the definition before you change it. Tools that flag

every such view as an issue are generating noise.

Heuristics, stated plainly

Checks 9 and 10 are heuristics. #9 matches a policy expression that mentions its

own table name — confirm by reading the policy. #10 matches only the leading

index column, so an unusual composite index can produce a false positive. Both

are deliberately tuned to over-report rather than miss something.

Tested against Postgres 17 / Supabase. Requires Postgres 15+ for the

security_invoker check; everything else works on 12+.

MIT. Take it, fork it, put it in your CI.

Built by David Borrás, who fixes these for a

living when reading the list is not what you wanted to do tonight.