Supabase checker
Your anon key isalready public
Every visitor to your app already holds it, because the frontend needs it. So the question is not whether the key is secret — it is what the key is allowed to read. Paste the project URL and the key, and this asks your database directly.
- No account needed
- Nothing stored
- Read-only
- Same engine as a connected scan
Run it
Two fields,
one result
The project URL and the publishable key — the one in your project’s API settings that starts with sb_publishable_, or the older anon key. Not the secret or service-role key: the endpoint refuses it, and rightly so — it bypasses row-level security entirely, so pasting it would prove nothing about what a stranger can reach.
- 10
- tables probed per run
- 5
- checks per project a day
- 20
- checks per address a day
- 0
- keys stored
What it asks
Four questions
your key answers
Nothing here is inferred from your schema or guessed from a framework. Each line is a request that either succeeded or did not, against your own project.
What the anon key can select
Each table the key reaches is read the way a stranger would read it: one request, no session, nothing written. A table that answers with rows is a table whose row-level security policy — or absence of one — just became public fact.
Row-level security, table by table
The result is per table, not per project. "RLS is on" is not the finding; "this table returns this many rows to anyone holding the publishable key" is, and that is what a connected scan reports with the evidence attached.
Storage buckets and their listings
Public buckets, and buckets whose object list the key can enumerate. A private bucket whose contents are reachable by a guessed path is a different failure, and the connected scan is the one that looks for it.
The auth configuration your key exposes
Whether anonymous sign-ins are enabled, whether email and phone confirmation are switched off, which providers are turned on. These decide how easy the first two rows are to reach.
A connected project also reads policies row by row, checks storage rules in depth, probes the edge functions you name, and runs the two-account isolation pass that asks whether one tenant can count another’s rows.
An exposed table does not announce itself. The publishable key is the only invitation it needs.
Stated plainly
Where the free
check stops
These are not marketing hedges — they are the caps the endpoint enforces, and it will refuse a run rather than exceed them.
Ten tables probed per run. A project with more tables than that scans the rest as unknown rather than quiet: bounded work beats unbounded exposure, on an endpoint whose whole job is reaching somebody else's backend.
Five checks per project a day, twenty per address. Refused requests are not counted against the window, so a typo does not spend your day.
Titles and severities only. What a finding means, the raw response behind it and how to fix it is what a connected account opens — the same line the rest of the product draws.
Nothing is stored. This endpoint writes no rows: not the key you paste, not the URL, not the result. The daily counters are the only thing that survives a run.
Read-only by construction. One select per table, one list per bucket — no writes, no logins, no state change, and no request to an address that is not your project.
Found something
you did not expect?
Connect the project and the same engine reads it in depth — policies, storage rules, edge functions and the isolation pass — inside the 85-check report that also covers the site in front of it. Free account, no card.