# Supabase RLS policy checker

> Paste Supabase policy SQL to find policies of true, sign-in-only checks, user_metadata roles, open storage buckets and exposed functions. Free; in your browser.

Canonical: https://app369.com/tools/supabase-rls-policy-checker/
Last updated: 2026-10-27

Paste the SQL that creates your row-level security policies (a migration, or your whole `supabase/migrations` folder) to find the policies that let the wrong people in: policies of true, sign-in-only checks, user_metadata roles, storage buckets anyone can list or write to, and security definer functions anyone can call. The check runs in your browser; your SQL is never uploaded.

[**Check my policies**](#check)

Free, no sign-up. Based on Supabase’s Security Advisor lints and Postgres policy rules.

Rules last checked October 27, 2026 against [Supabase’s and Postgres’s docs](#sources).

## Your policies

**Policy SQL**

## **Want the whole app checked and fixed?**

This tool only reads the SQL you paste. The Launch Check reviews the whole AI-built app (sign-in, data access, keys in the browser, Stripe webhooks and deploys) and ranks every issue with evidence and a fixed quote to fix it. $450, 3 business days, credited to the Rescue Sprint.

[**See the Launch Check **](https://app369.com/fixed-price/ai-app-rescue/)

Policies are one part of it: see the full [Supabase security review before launch](https://app369.com/blog/supabase-security-review-before-launch-2026/), and check new tables with the [grants and RLS checker](https://app369.com/tools/supabase-oct-30-checker/). Found a problem? See how we [fix Supabase RLS at a fixed price](https://app369.com/service/supabase-rls-fix/).

## **What the checker looks for**

<dl>

<dt>**Policies of true**</dt>
<dd>Insert, update or delete policies with using (true) or with check (true), which apply to other users’ rows too. Supabase’s database linter flags this as lint 0024 (“RLS Policy Always True” in its source, “Security policy allows unrestricted access” in its docs).</dd>

<dt>**Sign-in-only checks**</dt>
<dd>Policies that only test auth.uid() is not null or auth.role() = 'authenticated', so every signed-up user reaches every row.</dd>

<dt>**user_metadata in policies**</dt>
<dd>Roles or tenants read from user_metadata, which users can edit themselves with supabase.auth.updateUser().</dd>

<dt>**Policies with RLS off**</dt>
<dd>Policies on a table where row-level security was never enabled, or was disabled later, so the policies do nothing.</dd>

<dt>**Open with check**</dt>
<dd>Updates scoped by using but with check (true), so a user can hand a row to someone else or set role or plan columns.</dd>

<dt>**Storage buckets**</dt>
<dd>Policies on storage.objects that only check the bucket, so anyone they cover can list and download every file, or upload, overwrite and delete files in other users’ folders.</dd>

<dt>**Security definer functions**</dt>
<dd>Functions that bypass RLS, are still executable by anon or every user through supabase.rpc(), or have no fixed search_path.</dd>

<dt>**Overlapping and slow policies**</dt>
<dd>Several permissive policies for the same role and action (the loosest wins), auth.uid() evaluated per row, and policies with no TO clause.</dd>
</dl>

## **Questions**

<dl>

<dt>**Is my SQL sent anywhere?**</dt>
<dd>No. The check runs in your browser with JavaScript, and the SQL never leaves the page. Only an anonymous count of findings is recorded for usage statistics.</dd>

<dt>**How is this different from the Security Advisor in the Supabase dashboard?**</dt>
<dd>The Security Advisor checks your live database, which is the better source once a migration is applied. This tool reads SQL before it runs, so you can check a migration your AI builder wrote, or a pull request, before it reaches the project. Several of its checks follow the Advisor’s own lints.</dd>

<dt>**If the checker finds nothing, are my policies secure?**</dt>
<dd>Not necessarily. It reads the SQL text for common risky patterns. It can’t see policies changed in the dashboard or in earlier migrations you didn’t paste, what your functions do, or whether a policy matches what your app intends. Testing each policy as a second user is how you confirm it.</dd>

<dt>**Why is auth.uid() is not null not enough?**</dt>
<dd>Anyone can sign up for your app unless you close sign-ups, and your anon key ships inside it. A policy that only checks for a signed-in user lets every user read or change every other user’s rows through supabase-js.</dd>

<dt>**Why wrap auth.uid() in a select?**</dt>
<dd>Written as (select auth.uid()), Postgres can evaluate it once per query instead of once per row. The result is the same, and on large tables the query can be much faster. Supabase’s RLS guide recommends it.</dd>

<dt>**What should I paste?**</dt>
<dd>The files in supabase/migrations, in order, or the output of supabase db dump. Include the create table and alter table statements, so the checker can tell whether RLS is enabled on the tables your policies cover.</dd>
</dl>

Rules last checked October 27, 2026 against these sources: [Supabase row-level security guide](https://supabase.com/docs/guides/database/postgres/row-level-security), [Supabase database linter](https://supabase.com/docs/guides/database/database-linter), [Supabase splinter lint source](https://github.com/supabase/splinter/tree/main/lints), [Supabase Storage access control](https://supabase.com/docs/guides/storage/security/access-control), [Supabase securing your API](https://supabase.com/docs/guides/api/securing-your-api) and the [Postgres CREATE POLICY reference](https://www.postgresql.org/docs/current/sql-createpolicy.html). Using Firebase instead? Try the [Firebase Security Rules checker](https://app369.com/tools/firebase-rules-checker/). To check the live app too, paste its address into the free [AI app security check](https://app369.com/tools/ai-app-check/). It looks for secret keys in the app’s JavaScript. Other Supabase errors: [new row violates row-level security policy](https://app369.com/fix/supabase-new-row-violates-row-level-security/), [Edge Function blocked by CORS](https://app369.com/fix/supabase-edge-function-cors-error/) and [auth emails that link to localhost](https://app369.com/fix/supabase-auth-email-links-localhost/).

## **Link to this checker**

Writing about Supabase security, a starter template’s README or a forum answer about RLS? You’re welcome to link here. The checker is free, needs no sign-up, and never uploads the SQL.

**HTML link**

## **Fixed-price help for your app**

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

- [**AI-Built App Rescue**from $450A Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.](https://app369.com/fixed-price/ai-app-rescue/)
- [**App Fix Ticket**from $450One reproducible bug in an existing mobile or web app, diagnosed and fixed.](https://app369.com/fixed-price/flutter-firebase-bug-fix/)