The story
A week ago I built supabase-security, a small Node.js auditor that scans Supabase projects for over-permissive RLS policies. To test it, I scanned 100 random Supabase projects from GitHub.
22 out of 100 leaked user data anonymously. The pattern was consistent: dashboard says "RLS enabled ✅", policies say USING (true), anonymous curl returns the full table.
Then I ran the tool against my own production CRM (FitCRM, an e-commerce ops platform I've been running for 2 years). Found 14 critical leaks. Order tables open to anon. Storage buckets with predictable signed URLs. RPCs with SECURITY DEFINER bypassing RLS.
I wrote the postmortem yesterday.
After that, two thoughts:
- If this many random Supabase projects leak, what about every other BaaS?
- The "keyless" mode (parse repo + probe anon, no admin creds) is the magic — anyone can run it on any project, including ones they don't own.
What I shipped today
Five sister tools. All MIT, all on npm, all use the same --discover pattern:
1. supabase-security v0.4
npx supabase-security@latest --discover .
Parses from('table') / rpc('function') / storage.from('bucket') call sites, extracts SUPABASE_URL + SUPABASE_ANON_KEY from your repo, then probes the public REST API anonymously. Flags any table that returns rows.
2. pocketbase-security v0.2
npx pocketbase-security --discover .
Parses pb.collection('name') call sites, then hits /api/collections/{name}/records anon. Catches the legendary PocketBase footguns: empty rules (= fully public), @request.auth.id != "" (any signed-up user passes), || true leftover dev rules.
3. appwrite-security v0.2
npx appwrite-security --discover .
Parses databases.listDocuments(dbId, collId), probes /v1/databases/{db}/collections/{coll}/documents anon. Flags collections with the any role on Read permission, or users role with document security OFF.
4. firebase-security v0.2
npx firebase-security --discover .
Parses collection(db, 'x') / doc(db, 'x/y'), extracts projectId from firebase config or env, then GETs firestore.googleapis.com/v1/projects/{pid}/databases/(default)/documents/{collection} anon. Confirms the legendary if true / wildcard-match-all leak pattern.
5. nhost-security v0.2
npx nhost-security --discover .
Parses gql`queries for table names, auto-resolves the Hasura endpoint from subdomain+region (or env), POSTs anonymous queries against/v1/graphql. Flags tables where theanonymous` role has SELECT with permissive row filter.
The common pattern across every BaaS
Every BaaS has the same trap:
| BaaS | Footgun | Dashboard says |
|---|---|---|
| Supabase |
USING (true) on RLS policy |
"RLS enabled ✅" |
| PocketBase | Empty rule string | "Public" (in tiny text) |
| Appwrite |
any role on Read |
Permissions "configured" |
| Firebase | allow read: if true |
"Test mode" |
| Nhost |
anonymous role with {} filter |
"Permission configured" |
In every case, the dashboard makes the configuration look intentional. In every case, anonymous curl returns rows. The dashboards don't show you what an anonymous-role evaluation actually returns — only what your role (the developer, signed in) returns.
Why "keyless --discover" is the unlock
Traditional security audits need admin credentials. The dev says "audit my Supabase" and hands you a service-role key. That's a high-trust ask and creates friction.
The keyless mode flips it:
- Run
npx <stack>-security --discover .from any project directory - It reads your client code (which already knows what tables/collections/buckets exist)
- It probes the public API with the same anonymous credentials anyone on the internet has
- No admin auth, no key sharing, no install
You can run it against your own project before pushing, or against a friend's project they're worried about, or in a CI step.
Patterns I'd add next
Things I want to detect but don't yet:
- Cross-platform: Same project using Supabase + Stripe + Resend — credential leak in one breaks all three. Need a unified scanner.
- JWT signature secrets committed to repos (already detectable via gitleaks but I want the BaaS-specific impact analysis)
- Storage paths with predictable signed URLs — the FitCRM case
- Function call sites with SECURITY DEFINER bypassing RLS — PostgREST anti-pattern
- GraphQL introspection on Hasura instances exposing schema
Try it
Pick the stack you use most. The discover mode runs in seconds:
`bash
cd your-project
npx supabase-security --discover . # or pocketbase-security, etc
`
If you have a project worth a deeper audit, the paid $99 single-tenant audit report includes the manual review I did on my own CRM that found the SECURITY DEFINER RPCs and the predictable bucket paths. But the free CLI catches the common 70% of leaks.
Links
- supabase-security: github · npm
- pocketbase-security: github · npm
- appwrite-security: github · npm
- firebase-security: github · npm
- nhost-security: github · npm
All MIT. If you find issues, open a PR. If you find a leak in your own project — fix it before someone else does.
If you run --discover on your project and want a second pair of eyes on the findings, I do one-off paid audits ($99 single project, $249 multi-tenant). But honestly, the CLI catches most of it.
United States
NORTH AMERICA
Related News
What Does "Building in Public" Actually Mean in 2026?
20h ago
The Agentic Headless Backend: What Vibe Coders Still Need After the UI Is Done
20h ago
Why I’m Still Learning to Code Even With AI
22h ago
Students Boo Commencement Speaker After She Calls AI the 'Next Industrial Revolution'
5h ago

Testing for ‘Bad Cholesterol’ Doesn’t Tell the Whole Story
5h ago