2026-10-15 · The Rivyva team · eight minute read

Is your Supabase data public? How to check in five minutes

If your app uses Supabase, your database is reachable from the internet by design. That's how the browser talks to it. What keeps each row limited to the right person is a set of rules called row-level security, or RLS. When RLS is off on a table, anyone with your project's public key (which is in your site's code) can read that table.

The anon key is meant to be public. It identifies the project. It is not a password. The rules on each table are what decide who can read and write.

In the Supabase table editor, open each table and look for row-level security. If it is off, treat that table as public until you have checked.

You can also try a read without logging in. From a terminal, call the REST URL for one table with the anon key in the apikey header and ask for a single row. If you get data back, the table is readable by anyone who can see your site's code. Do this only on a project you own.

A first policy for a table that has a user_id column is: enable row-level security, then allow select where auth.uid() equals user_id. Repeat for insert, update and delete if those should be limited too.

Watch for three traps. A policy that says true lets everyone through. A role stored in user_metadata can be edited by the user. A service-role key in browser code bypasses the rules entirely.

Before you ship, open the app as two different users and confirm each one only sees their own rows.

Vitals can spot a public read from the outside. A repo scan also looks for tables without RLS, policies that allow anyone, roles in user_metadata, and a service key in the bundle. The check pages are DB-001, DB-002, DB-003, AUTH-003 and SEC-003.

Source: https://supabase.com/docs/guides/database/postgres/row-level-security

What to do next

Run a free Vitals check on your live URL. It only reads public pages.

Get free Vitals

Related

Is your Supabase data public? How to check in five minutes — Rivyva