Supabase RLS is disabled. Is my data public?

Also searched as: Supabase RLS disabled in public · Supabase RLS · Supabase RLS policy · Supabase anon key exposed · Supabase anon key public

Updated 3 October 2026

Short answer

Very possibly. Supabase's documentation says a table in an exposed schema (such as public) without Row Level Security is readable and writable by any role with a grant on it, and the public key that carries that role is inside your app for anyone to find. Turn RLS on for every table in an exposed schema, write policies for exactly what each user may see and change, and keep the secret key (formerly service_role) out of the browser entirely.

What's the problem

Your app reads and writes data straight from the browser using Supabase's public key. That's normal for Supabase, but it means your policies are the only thing deciding who sees what. If a table has RLS switched off, anyone with your public key, which is anyone who opens your site, may be able to read it or change it.

Why it happens

  • RLS gets switched off to make errors go away. With RLS on and no policies, queries return nothing. Turning it off "fixes" that, and everything is exposed.
  • The public key is public by design. The publishable key, which replaces the older anon key, only reaches what RLS allows. With RLS off, that's everything.
  • The secret key ended up in the frontend. The secret key, which replaces the older service_role key, bypasses RLS entirely. If it's in browser code, policies don't matter.
  • New tables start unprotected. Every new table needs RLS enabled and its own policies. It's easy to add one and forget.

How to fix it

  1. List every table in your exposed schemas in the Supabase dashboard and check RLS is enabled on each.
  2. Write a policy per action (select, insert, update, delete) that matches what users should do. Usually: users can only act on rows where the owner column matches their own user ID.
  3. Search the frontend for the secret key (service_role or sb_secret_). If it's there, move that work to a server or Edge Function, and rotate the key.
  4. Test as an attacker. Using only the public key, signed out and then signed in as a second user, try to read and change another user's rows.
  5. Plan the key switch. Supabase is replacing the legacy anon and service_role keys with publishable and secret keys, and is deprecating the old ones by the end of 2026.
  6. If tables were open while real users were on the app, check what was exposed. See do I have to report a data breach.

When to call Preventionlabs

If you have a few tables with clear ownership, the steps above will get you there. Call us when the schema is large, the app was generated by a tool and depends on open tables to work, or switching RLS on breaks half the features. Access control and data exposure are on the MVP-level protection checklist in every resurrection, tested by trying to reach other users' data with your own public key, then fixed.

Submit your project for a free assessment

Free assessment. $10,000 AUD flat to get it live, only if we take it on and you go ahead.

Sources

  1. Supabase: Row Level Securityplatform docsA table in an exposed schema without RLS is readable and writable by any role with a grant on it.
  2. Supabase: Row Level Securityplatform docsEnable RLS on every table in an exposed schema.
  3. Supabase: API keysplatform docsPublishable key Anyone can read it, so it only reaches what Row Level Security allows
  4. Supabase: API keysplatform docsSecret key It bypasses Row Level Security, so it must never leave your control
  5. Supabase: API keysplatform docsSupabase is deprecating the anon and service_role keys by the end of 2026.
← All of Is it safe?