Prevent Supabase RLS bypass
Row Level Security is the only thing standing between your anon key and your data. That key ships in the client bundle and is public by design, so any table PostgREST exposes without a working policy is readable by anyone who opens devtools.
There are three distinct ways to get this wrong, and they fail differently. RLS switched off entirely. RLS on with a policy that is a constant true. And a write policy with nothing constraining what gets written. VibeGuard checks all three on every scan.
Rules that check this
- criticalRow Level Security disabled
RLS_DISABLED - criticalPolicy always evaluates to true
RLS_TAUTOLOGY - highWrite policy without WITH CHECK
MISSING_WITH_CHECK - highRLS enabled but no policies
RLS_NO_POLICIES
RLS disabled is the loud one
A table with `relrowsecurity = false` in a PostgREST-exposed schema returns every row to an unauthenticated request. This is what almost every reported Supabase data leak turns out to be.
It is also the easiest to check, and the query below is exactly what VibeGuard runs — reading `pg_catalog` only, never your data.
SELECT n.nspname AS schema, c.relname AS table
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r', 'p')
AND n.nspname = 'public'
AND c.relrowsecurity = false;A policy that says true is worse than no policy
`USING (true)` is the quiet failure. RLS is enabled, so every dashboard and advisor reports the table as protected, while the policy grants every row to every role it targets.
Two cases are deliberately not flagged, because reporting them is noise: a RESTRICTIVE policy can only ever narrow access, so `USING (true)` on one grants nothing; and a policy scoped to `service_role` is decorative, because that role already carries BYPASSRLS. The Supabase dashboard generates exactly that policy.
Writes need their own clause
A SELECT policy governs what a caller can read. It says nothing about what they can write. An INSERT policy without WITH CHECK lets a caller create rows attributed to anybody.
For UPDATE and ALL, Postgres falls back to the USING expression when WITH CHECK is absent. That is usually right and silently wrong the moment read and write conditions are meant to differ — so VibeGuard flags it and says which case you are in.
Frequently asked
- Does enabling RLS break my app?
- It denies everything until a policy grants access, so yes, until you add policies. VibeGuard generates the four owner-scoped policies from your actual column names so you can enable and grant in one paste.
- Is FORCE ROW LEVEL SECURITY necessary?
- Without it the table owner bypasses every policy — and a Supabase migration or psql session runs as the owner. The generated SQL always includes it.
- How is this different from the Supabase Security Advisor?
- The advisor is a point-in-time check you have to remember to open. VibeGuard runs on a schedule, diffs against the last run, and tells you when something that was fixed comes back.
Check your project in about ten seconds
Paste a URL. No signup, no writes, nothing stored.
Run the free audit