Free read-only SQL script that lists RLS gaps in a Supabase project #51631
Replies: 1 comment
|
Solid scope — the 16-check single-SELECT approach is the right shape for this (zero-install catalog reads are what people actually run). Feedback on the heuristic classes from scanning 100+ public Supabase repos for exactly these patterns: The highest false-positive-rate class: "signed in treated as ownership." The dominant shape in the wild is Views: the PG15+ distinction matters. Column-level grants add a layer the write-policy checks can't see. Postgres supports per-column grants: a policy may allow The user_metadata class: the heuristic that saves the most debugging is distinguishing metadata as the sole authorization (dangerous) vs. metadata in combination with ownership (usually fine — e.g., One addition for the storage checks: public buckets without an owner check are worth flagging, but the same check should look at For calibration data if useful: in the public-repo scans, the roughly-sorted prevalence is permissive Good call publishing the test database next to it — the reproducibility is what makes false-positive feedback actionable. Following the script's development. |
Uh oh!
There was an error while loading. Please reload this page.
A common problem in apps built fast, especially with AI tools: one signed-in user can read or change another user's rows, because a policy only checks that the caller is logged in, a view skips Row Level Security, or a user can update their own plan column.
I wrote a single SQL query that reads the database catalog and lists these problems by severity. It has 16 checks, including: tables the API can reach with RLS off or with no policy; policies that let every row through, apply to anon, or treat "signed in" as ownership; views and materialized views that bypass RLS; SECURITY DEFINER functions callable via /rpc or without a fixed search_path; public buckets and storage policies without an owner check; write policies that let users create rows in someone else's name or edit their own role or plan; access decided by user_metadata.
It only reads. It is one SELECT over catalog tables, and I ran it inside a read-only transaction against a Supabase-like test database, where Postgres rejects any write. The test database is published next to the script. Five checks are heuristics and can misfire, so please treat a finding as a lead, not a verdict.
How to run: open the SQL Editor, paste the file, run once. If your Data API exposes schemas other than public, add them at the top.
Script and instructions: https://rowproof.pages.dev/download.html
Feedback on false positives is welcome.
All reactions