Skip to content
TakeoverWork
Free tool

Supabase RLS Checker

Paste your Supabase SQL and see which tables anyone with your public key could read or change.

Runs 100% locallyThe SQL you paste is analysed in your browser and never leaves your device.

Runs 100% in your browser — nothing you paste is uploaded.

Paste migrations or the output of a schema dump. Parsed in your browser.

Results

Paste your SQL (or load the sample) to see tables, RLS status and risky policies.

Next step

Stuck? Post your takeover free

Describe what works, what's broken and what's left. Developers who finish and rescue projects will contact you.

Post your takeover free

Supabase lets your front end talk to the database directly, using a public key that ships in your app. That is convenient, but it means row level security (RLS) is the only thing standing between your data and anyone who opens the browser developer tools. Apps built quickly, especially with AI builders, often have tables with RLS switched off or policies that allow everyone. This checker reads the SQL you paste and points out those gaps. It runs in your browser and never connects to your project.

What the checker flags

  • Tables without RLS enabled. Any table in an exposed schema, usually public, without alter table ... enable row level security can be read and written by anyone holding the anon key.
  • using (true) policies. A policy that returns true for every row. Sometimes intended for public data, often a placeholder that was never replaced.
  • Missing or empty with check. using decides which existing rows a caller can see or target. with check decides which new or changed rows are allowed. Insert policies only use with check, and update policies should state both so a user cannot move a row into someone else's account.
  • Policies that never mention auth.uid(). A policy that does not compare against the signed-in user, or a role or membership table, often lets one user reach another user's rows.
  • Service-role hints. Comments, function bodies or settings that suggest the service-role key is used where client code can reach it.

How to read the results

Start with the tables that hold personal or paid-for data: profiles, orders, messages, files, subscriptions. A missing RLS flag on one of those is the most urgent finding. Next, look at write policies (insert, update, delete), because a bad write policy can corrupt or wipe data, not just expose it. Then review using (true) select policies one by one and decide whether that data is really meant to be public.

A table with RLS enabled and no policies at all is locked: nobody can reach it through the API except the service role. That is safe, but if your app needs the table, it will look broken until you add the right policy.

A correct example policy set

This example lets signed-in users read, create and edit only their own notes:

alter table public.notes enable row level security;

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

create policy "Users can create their own notes"
on public.notes for insert
to authenticated
with check ( (select auth.uid()) = user_id );

create policy "Users can update their own notes"
on public.notes for update
to authenticated
using ( (select auth.uid()) = user_id )
with check ( (select auth.uid()) = user_id );

The using clause on the update policy limits which rows a user can target. The with check clause stops them from changing user_id to someone else's ID. Wrapping auth.uid() in a select follows Supabase's performance advice, because the value is worked out once per query instead of once per row.

Fixing common problems

  • RLS off on a table the app needs: enable it, then add the narrowest policies that keep the app working. Test as a signed-in user and as an anonymous visitor.
  • Placeholder using (true): replace it with an ownership rule like the example, or a membership check against a team table.
  • Admin features failing under RLS: move them to a server-side function that uses the service-role key, rather than loosening the policy for everyone.
  • Service-role key in front-end code: rotate it in the Supabase dashboard straight away, then remove it from the code. The Secret Leak Scanner can confirm it is gone.

Limitations

The checker reads SQL text, so it only knows what you paste. It does not see the live database, storage bucket policies, or logic in functions and views defined elsewhere. A clean result does not prove your data is safe; it means the common mistakes were not found in that SQL. Results are guidance, not a security audit. After changes, test with real accounts, and check the security advisor in the Supabase dashboard as well.

Learn more

Our guide on why Lovable, Bolt and v0 apps break in production explains how RLS gaps appear in generated apps. The prototype to production checklist puts RLS alongside the other launch checks, and developers inheriting a Supabase project will find a review order in your first week on an inherited codebase.

Still seeing errors after fixing policies?

If sign-in fails or data vanishes once RLS is on, see Supabase auth or RLS broken. If you would rather have someone who knows Supabase fix it properly, post your takeover for free and paste the checker's findings, not your keys, into the description.

Frequently asked questions

Where do I get the SQL to paste?

Use the migration files in your project's supabase/migrations folder, or export the schema with the Supabase CLI. You can also copy table and policy definitions from the SQL editor in the Supabase dashboard.

Is a using (true) policy always wrong?

No. A select policy with using (true) is fine for data that really is public, such as a product catalogue. It is a problem on tables that hold user data, and on insert, update or delete policies, where it lets any caller change rows.

My app works, so why does the checker report problems?

An open table usually works perfectly, which is why the problem goes unnoticed. The issue is that anyone with your public anon key, which is visible in your front-end code, can call the database API directly and skip your app's screens.

Does the checker connect to my Supabase project?

No. It only reads the SQL you paste, in your browser. It cannot see the live database, so if the dashboard and your migration files differ, check the live policies too.

Can I just use the service-role key to make errors go away?

Not in client code. The service-role key bypasses row level security completely, so putting it in a browser or mobile app gives every user full database access. Keep it on the server, such as in an edge function, and fix the policies instead.

Free tools that help

Related guides

Related problems