Supabase security · 6 minute read
Documents-only Supabase RLS review: what it can prove, and what it cannot
Some teams cannot hand over repository access or database credentials before a contract is signed — sometimes for good reason, sometimes because the project is pre-launch and the data is sensitive by nature. A documents-only review is the scope for that situation: you send the schema, the migrations, the policy definitions and a config snapshot, and the review is done from those. This article states precisely what that scope settles and what it leaves open, so you can decide before paying whether it answers your question.
What "documents-only" actually means
The reviewer receives no repository access, no service_role key and no database connection. What arrives instead is a packet you assemble: the schema dump or migration history, the policy definitions (SQL or dashboard exports), the client configuration including the project URL and the public anon key, and any evidence you already hold — a scan output, a screenshot of the dashboard, logs. Read-only probes against your own REST endpoint using the public anon key are still part of the review, because that endpoint is public by design and everything it returns is already public.
The boundary that matters: the review can prove what your configuration authorizes, using the artifacts plus the public surface. It cannot prove what the live database is doing right now beyond that surface, because it never sees the live database.
What a documents-only review settles
- Whether RLS is enabled where you think it is. Enabled at the table level, per table — a table with policies but RLS off enforces nothing, and a table with RLS on and zero policies denies everyone including you.
- What the policies actually say. Permissive vs restrictive, the role each policy applies to, the
qualandwith_checkexpressions — includingtrue,{public}andauth.uid() is nullvariants that pass a casual read and fail a hostile one. - Whether grants survive your policies. RLS filters rows; it does not revoke table privileges. An
anonrole that still holdsSELECTon an RLS-protected table reads everything the policies let through — and if a policy is permissive, that is everything. - Which paths bypass RLS by construction.
security definerfunctions and their search paths, views withoutsecurity_invokerthat expose base-table rows with the view owner's privileges, and the Data API endpoints that expose them. - What the public anon key can reach today. A live read-only probe of your REST and storage endpoints — table row counts, storage object listings — sized from your own endpoint, with no login.
- Where secrets live. Service keys in tracked files, environment files in the packet, hardcoded fallbacks in client bundles — and whether history shows a key that is still valid.
What stays open until a runtime pass
- Whether a repaired policy actually isolates at runtime.The repaired SQL is inspectable; the proof that tenant B's session gets an empty array for tenant A's row needs two real sessions against a staging clone.
- How much was exposed, and for how long. Row counts today are visible. Historical exposure needs audit logs or a retention window your database settings define — not something a document set contains.
- Whether grants drifted since the packet. The packet is a snapshot. Dashboard edits, a restore from an older backup or a direct role change after the snapshot are invisible to it — one reason the runtime pass re-checks grants against the live clone, not the packet.
- Whether a leaked key was used by anyone else.The packet proves the key is valid; only your project's logs show whether it was called, from where, and what it touched.
- Concurrency and interaction with older clients. Retry, replay and expired-token behavior are properties of the running system plus deployed clients, not of the migration files.
Why buyers choose this scope anyway
Because it is escrow-safe and fast. No credentials are shared, so nothing to rotate afterward; the packet can be assembled in an afternoon; and the findings arrive ranked with evidence attached, which is what an implementer needs and what a board-level summary cannot substitute. For a pre-launch project it is often the only scope available, and the findings it produces — permissive anon policies, surviving grants, definer bypasses — are the ones that account for the majority of real Supabase data exposure. A review that stops there, and says so, is worth more than one that guesses past its evidence.
What to send, and what comes back
Send: the schema dump or full migration history; policy definitions (SQL or dashboard export); the client config with project URL and anon key (never the service_role key); any evidence you already have — a scan output, screenshots, logs. Typical packets run 5–40 files. If the packet grows past the fixed scope, the scope conversation happens before funding, not after.
Get back: a ranked findings report — HIGH first, each finding with identity, description, evidence, impact, one recommended repair and a verification method; a runtime-evidence checklist that states per finding which questions the documents answer and which need the staging harness; and an implementer brief an engineer can apply without the reviewer. Turnaround is five business days for a full packet, with one clarification round included — and corrections of factual errors or missing agreed deliverables do not count against it.
The honest summary: documents-only settles everything your configuration authorizes, proves what the public surface exposes, and marks the rest as unverified rather than closing it. If your question is "is this configuration safe to launch", that is usually exactly the answer you need — and the checklist it leaves behind is what turns the fixed-price audit from $99 into a closing procedure rather than another document.
Run the checks yourself first
Supabase RLS Audit Kit · $29 one-time
The seven commented audits this scope runs — policy census, grant census, anon-key probe, definer and view bypass, storage, bundle scan — as SQL and curl you run in your own project, plus the role-simulation harness that turns the checklist into a green or red answer.
Get the kit - $29 ↗Review the files, scope and license →Related reading: a redacted sample of what a delivered review looks like, 7 ways your Supabase app still leaks data with RLS enabled and how to test RLS policies as every identity that calls your API.