rls-recon
v0.1.0
Published
Audit your own Supabase project's Row Level Security from the outside: what can the public anon key actually read, write, or list? Zero dependencies, read-only by default.
Maintainers
Readme
rls-recon
Audit your own Supabase project's Row Level Security from the outside, using nothing but the two things every client app already exposes: the project URL and the public anon key. One command answers the question that matters: what can an anonymous stranger actually read, write, or list?
Zero dependencies. Node 18+. Read-only by default.
AUTHORIZATION REQUIRED. Run rls-recon only against projects you own or have explicit written authorization to test. See Responsible use and disclaimer below. It is not optional reading.
Why
Supabase's anon key is public by design; it ships in every browser bundle and mobile app. The entire security model rests on Row Level Security being configured correctly on every table, every RPC, and every storage bucket. Most projects get this wrong somewhere, and the failure is silent: everything works in the app while the data sits open to anyone with curl.
rls-recon makes the same requests an anonymous caller would make and reports exactly what your policies allow. It does not bypass anything. It asks the server "what does this key get?" and shows you the answer.
Usage
node bin/rls-recon.mjs --url https://your-project.supabase.co --anon-key YOUR_ANON_KEYFlags:
--probe-writesalso test anonymous INSERT. Requires--i-own-this-project. Inserts one canary row per table built from column defaults and deletes it immediately after, matched on the returned values.--i-own-this-projectattestation required to enable write probes.--delay-ms Npause between requests (default 150; sequential and gentle on purpose).--timeout-ms Nper-request timeout (default 10000).--jsonraw JSON result instead of the report.
Exit codes: 0 no anonymous data access found, 1 findings present, 2 error. The non-zero exit makes it usable as a CI gate: RLS regressions break the build instead of reaching production.
Example output
rls-recon report for https://your-project.supabase.co
probed at 2026-08-23T14:00:00.000Z with the provided anon key
TABLES (4 exposed in the API schema)
READABLE profiles (rows exposed: 1204, columns: id, full_name, email, phone, created_at)
READABLE orders (rows exposed: 57, columns: id, user_id, total_cents, status)
READABLE products (rows exposed: 340, columns: id, name, price_cents)
denied audit_log
RPC FUNCTIONS (2 exposed to this key)
exposed search_docs
exposed nearby_clinics
STORAGE
bucket avatars (public, OBJECTS LISTABLE)
bucket invoices (private, OBJECTS LISTABLE)
SUMMARY
readable tables: 3
writable tables: 0
buckets visible: yes
buckets with listed objects: 2
FINDINGS PRESENT: anonymous callers can reach data. Exit code 1.What it does
- Discovers the tables, views, and RPC functions the API schema exposes to your key (the server publishes this itself at
/rest/v1/). - Read-probes each table with a single
GET ...?limit=1and a count header: a 200 means the anon role can read it, and the report shows how many rows and which columns. - Lists storage buckets and checks whether object listing works for each. A "private" bucket that allows listing is still leaking.
- Write-probes (opt-in only): inserts a canary row from column defaults, deletes exactly that row, and reports whether anonymous inserts are possible.
What it does not do
- No bypass attempts. It uses only the credentials you provide and never tries to escalate past them. No SQL injection probing, no auth tricks, no service-key hunting.
- No target discovery. It takes an explicit
--url. There is no enumeration, no search integration, no batch mode. It can only point where you point it. - No unfiltered writes. It never issues UPDATE or DELETE probes against existing rows. Write probes insert a clearly-marked canary and remove it.
- No concurrency. Requests are sequential with a delay. It cannot be mistaken for a denial-of-service attempt.
Tests
npm testThe suite runs the full probe pipeline against a mock Supabase project: discovery, read probes, canary insert/delete with cleanup verification, storage listing, finding detection, exit-code logic, and report rendering. No network required.
Responsible use and disclaimer
rls-recon is a defensive audit tool. It exists so you can verify the security posture of systems you are responsible for.
- Run it only against projects you own or have explicit written authorization to test. If you are not sure whether you are authorized, you are not.
- You are solely responsible for how you use this tool and for complying with all applicable laws and the terms of service of any system you run it against.
- The author provides this tool as-is, without warranty of any kind (see LICENSE), and accepts no liability for any misuse of this tool or for any damage, claim, or loss arising from its use or inability to be used.
- A clean result is not a guarantee of security. rls-recon checks anonymous access through the public API surface; it is one layer of an audit, not the audit.
License
MIT
