How to Check If Your Supabase Is Secure
Supabase is the default backend for AI-built apps, which makes "how do I check if my Supabase is secure?" one of the most important questions a vibe coder can ask. The reassuring part: auditing your Supabase security is a concrete, repeatable process, not guesswork. This guide gives you four checks — is Row Level Security really on, are your policies actually scoped, are your keys exposed, and can an unauthenticated user read your data — plus how to testeach one rather than assume it's fine.
Check 1 — Is Row Level Security really enabled?
Row Level Security (RLS) is the setting that decides whether your public anon key can read the whole database or only what a user is allowed to see. New Supabase tables ship with RLS off, so the first check is simple: in the Supabase dashboard, open the table editor or the Authentication section and confirm that every table holding user data shows RLS enabled. Don't stop at the tables you remember creating — check all of them, because one forgotten table with RLS off is enough to expose everything in it. If you're new to RLS, read what RLS is and why every Supabase app needs it first.
Check 2 — Are your policies actually scoped?
RLS being "on" is necessary but not sufficient. Enabling RLS with no policies blocks all access; adding an overly broad policy (for example, one that allows any authenticated user to select any row) quietly re-opens the door. So the second check is to review each table's policies and confirm they scope rows to their owner — typically comparing the row's user column against auth.uid(). A table with RLS on but a "true" policy is no safer than one with RLS off. Read every policy and ask: "does this let someone see rows that aren't theirs?"
Check 3 — Is your service-role key exposed?
Supabase gives you two keys, and the difference is everything. The anon key is safe to ship in the browser as long as RLS is enabled, because RLS enforces access. The service-role key bypasses RLS entirely and has full admin access to your database — it must live only on the server and never appear in client code, a public bundle, or a committed .env. Search your deployed site's source for the string service_role, and check your repository history. If it's anywhere public, rotate it immediately. Our guide on finding exposed API keys shows the exact steps.
Check 4 — Test it like an outsider
The most convincing check is to behave like an attacker for two minutes. Using only your public anon key — the same one that's in your app — try to query a table that should be private, with no user logged in. If you get protected data back, your RLS is missing or misconfigured. Then log in as one test user and try to read a different user's rows by their ID. Anything you can reach that you shouldn't is a real, exploitable exposure. This test turns an abstract "is it secure?" into a concrete yes or no.
Common Supabase mistakes this audit catches
- Tables created after launch that never had RLS turned on.
- RLS enabled with a permissive policy that allows any user to read any row.
- The service-role key pasted into client code or an environment variable exposed to the browser.
- Storage buckets left public when they hold private files.
- Database functions that run with elevated privileges and skip their own access checks.
For a deeper look at how these go wrong in practice, see how a Supabase misconfiguration exposes records.
Automate the outward checks
You should always review policies in the dashboard yourself, but the outward-facing signs — an exposed service-role key, anon-key data exposure, and related misconfigurations — can be checked automatically. Paste your live URL into Sayver's free website security scanand it flags these in plain English, so you know within a minute whether your Supabase-backed app is leaking. Then, if you're hardening the whole stack, follow how to secure a Supabase app built with AI tools.
Frequently asked questions
How do I check if my Supabase database is secure?
Run four checks: confirm Row Level Security is enabled on every table (not just created, but ON), verify each table has policies that scope rows to their owner, make sure your service-role key never appears in client-side code, and then actually test it by querying as an anonymous user to confirm you can't read protected data.
How do I know if Row Level Security is actually on?
In the Supabase dashboard, check the RLS status for each table under Authentication or the table editor — every table holding user data should show RLS enabled. A subtle trap: enabling RLS with no policies blocks everything, and adding an overly broad policy re-opens it. Verify both that RLS is on and that the policies are correctly scoped.
What's the difference between the anon key and the service-role key?
The anon key is safe to ship in the browser as long as RLS is enabled, because RLS enforces who can see what. The service-role key bypasses RLS entirely and has full admin access — it must live only on the server and never appear in client code or a public repo.
How can I test my Supabase access controls?
Try to read protected tables using only the public anon key (the same one in your app) with no logged-in user. If you get data back that should be private, your RLS is missing or misconfigured. Then repeat while logged in as one user, trying to read a different user's rows.
Can a scanner check my Supabase security for me?
A scan of your live app detects the outward signs — an exposed service-role key, anon-key data exposure, and related misconfigurations. Sayver's free scan flags these; for a full policy-by-policy review you also check the dashboard directly.