FREE SCANS · Full reports and fix prompts are always free. Explore Builder, Pro and Agency monitoring ↗ · Share your feedback ↗
Supabase Row Level Security

Supabase RLS checker

Learn how to review public keys, database grants and row policies, then test access with two accounts. Start with a website scan; database tests, including a two-account check of whether users can read each other’s rows, unlock after you publish a one-time ownership token from inside your Supabase project.

Only scan authorized sites. Read the testing rules. Reports are private to this browser; keep its cookies to retain access. Use is subject to our Terms of Service.

Enter a public web page, such as your-app.com. APIs and downloads cannot be scanned here.

✓ No signup✓ Read-only✓ Masked evidence

How to check whether Supabase RLS protects your rows

Finding a public key is not the same as finding public data. Start with a clear access rule, inspect the existing configuration, then prove both the allowed and denied cases using invented records in your own test project.

Grants and RLS answer different questions

Table grants determine which operations a database role may attempt. Row Level Security policies determine which rows that operation may affect. A readable exposed table without RLS can disclose data to a role with a SELECT grant. An enabled-RLS badge alone is also insufficient: the policy must match your intended access. See Supabase’s RLS guide.

A publishable key or legacy anon key can belong in client code. A Supabase secret key or legacy service_role key has privileged access and must stay server-side. Test client permissions using ordinary user sessions, not a privileged client. Supabase documents these differences in its API-key guide.

ILLUSTRATIVE EXAMPLE · EXPECTED BEHAVIOR

Too broad for private notes

A read policy applies to anonymous visitors and permits every row they can reach.

using (true)

Intended private access

An ordinary signed-in user can read rows assigned to that user.

auth.uid() = user_id
The intended rule depends on the product. A public catalog may deliberately allow public reads; private notes should not.

Inspect all the rules that apply

Write down which tables contain private data, which roles need each operation, and whether access belongs to an individual or a tenant. Inspect existing table grants and policies in your project. This read-only query lists policy definitions for the example table name; replace it with a table you own:

select schemaname, tablename, policyname,
       permissive, roles, cmd, qual, with_check
from pg_policies
where schemaname = 'public'
  and tablename = 'stacksnack_demo_notes';

This policy listing does not show table grants or prove runtime access. Review those separately. PostgreSQL normally combines applicable permissive policies with OR, so adding a narrower policy does not cancel a broader one. Table owners and bypass roles can behave differently from ordinary client roles. The PostgreSQL row-security documentation explains these interactions.

Do not remove a policy just because its name sounds broad. Establish what it permits, whether public access is intentional, and which workflows would change. Review exposed views, storage and server endpoints separately.

Understand a SELECT policy before adapting it

Assume a staging-only table named public.stacksnack_demo_notes already exists with a user_id UUID column matching each note’s owner. This example gives ordinary authenticated users read access to their own rows. It does not create accounts, seed data, or secure your other tables.

-- Illustration for the existing staging-only demo table.
-- Review existing policies before adapting this example.
alter table public.stacksnack_demo_notes
  enable row level security;

revoke all on table public.stacksnack_demo_notes
  from anon, authenticated;
grant select on table public.stacksnack_demo_notes
  to authenticated;

create policy "Demo owners read their own notes"
on public.stacksnack_demo_notes
for select to authenticated
using ((select auth.uid()) = user_id);

This is a read-only client model. The revoke statements remove client write privileges on this demo table. If your app needs writes, design separate INSERT, UPDATE and DELETE grants, policies and tests. Do not apply the snippet unchanged to an existing production table. Existing broad policies must be reviewed; this snippet does not remove them.

For multi-tenant data, ownership by a single user_id is usually not the full access model. Define membership, tenant boundaries and administrative roles explicitly. A signed-in user should not gain another tenant’s records merely by changing a request parameter.

Test allowed and denied access

Seed invented notes for two test accounts in staging. First confirm the fixtures exist through an authorized setup path. Then test as the real client roles; a query in an administrative SQL editor is not a substitute.

Test plan for the example SELECT-only policy
CaseExpected result
Signed-out requestCannot read either private test note. With the demo’s revoked grant, expect a permission error.
User A reads A’s noteReturns the known A-only fixture. Proves allowed access still works.
User A requests B’s noteReturns no B-only row or contents.
User B requests A’s noteReturns no A-only row or contents.
Either client attempts a writeDenied in this SELECT-only example. Test your actual write rules separately.

An empty response by itself proves little: the table might be empty, the filter might be wrong, or you might be using the wrong project. Pair every denial with a known fixture and a working allowed case. Capture whether the result was a permission error or a filtered result, rather than treating every failure as the same thing.

Turn the cases into repeatable database and application tests. Supabase’s testing documentation covers local test workflows. Keep tests with the migration and rerun them after policy changes.

What StackSnack checks—and what it doesn’t

Start with a website scan of public code, known dependency signals and security headers. Website verification unlocks deeper exposed-file checks. Separately approved backend checks can attempt bounded anonymous reads and report masked evidence; they do not persist returned database rows. A URL scan does not log in as users A and B, test every policy operation, or certify tenant isolation.

Read the actual report’s warnings and coverage, even when it has no findings. Continue with the Lovable walkthrough or launch checklist. StackSnack is independent of Supabase.

A little check before you serve.

Bite-sized security checks. Clear security reports, with practical fixes and AI prompts.

Check my stack