VibeRaven
What does using (true) mean in a Supabase RLS policy, and when is it wrong?
using (true) means the policy matches every row, for every role it applies to. If the policy has no to clause, Postgres applies it to every role: "The default is PUBLIC, which will apply the policy to all roles." So a select policy with using (true) lets anyone holding your anon key read every row, which is fine for content that is meant to be public. On update, delete or all, it lets anyone change or remove every row, which is almost never intended. Read the using and with check clauses, not the policy name: a policy can be called "Owners can update their agents" and still be using (true). And a policy for the service role is never needed, because Supabase says the service role "has the bypassrls attribute".
Why this matters
Coding agents often write a policy to make a failing query work, and using (true) is the shortest policy that makes every query succeed. The name usually describes the intent ("Users can view their own profile", "Admins can delete pets") while the clause grants everything, so the migration looks right when you skim it. Two more patterns repeat: a policy named for the service role, such as "Service role can manage all sessions", with no to clause and using (true), which opens the table to everyone else; and an update or all policy with using (true) and no with check, where Postgres uses the using expression for new rows too, so any values can be written.
What we do not know yet
- Which of your policies are live. A migration can be changed later in the Supabase dashboard; the SQL below reads the live project, while a repository check reads only the files.
- Whether a using (true) select policy on your table is intended. That depends on whether the data is meant to be public, which only you can decide.
How to find using (true) policies and replace them
- List every policy in the public schema that lets everyone through. Run this in the SQL editor of the live project:
select tablename, policyname, cmd, roles, qual, with_check from pg_policies where schemaname = 'public' and (qual = 'true' or with_check = 'true'); - Read the cmd column first. A select on content that is genuinely public is fine. update, delete or all with qual = true lets anyone who can reach the table change or remove every row.
- Ignore the policy name and read qual and with_check. The name is what a reviewer skims; the clause is what Postgres enforces.
- Replace an open per-user policy with one that checks who the caller is, for example:
drop policy "Owners can update their agents" on public.agents; create policy "Owners can update their agents" on public.agents for update to authenticated using ((select auth.uid()) = owner_id) with check ((select auth.uid()) = owner_id); - Delete policies written for the service role. The service role bypasses row level security, so it never needs a policy, and a service role policy without a to clause applies to every role.
- For update and all policies, add a with check clause. Postgres says that if no with check expression is defined, "the USING expression will be used" for new rows too, so using (true) alone lets any values be written.
Optional repo check
For AI-built Vercel + Supabase apps, `npx -y viberaven@1.6.1 check` reads the migrations in the repo and flags using (true) policies with the file and line. In runs on 2026-10-02 and 2026-10-03 it flagged a select policy with using (true) as `rls_policy_allows_all_read` ("lets anyone, signed in or not, read every row") and an update policy with using (true) as `rls_policy_allows_all_write` ("lets anyone, signed in or not, update every row, to any values"). It reads only files: it cannot see a policy changed in the Supabase dashboard, so run the SQL above against the live project too. It is advice, not a gate, and a repository check, not a live database or security test. It exits with code 1 when it finds a blocker and writes a `.viberaven` folder that it does not add to `.gitignore`.
Related guides
Sources
Is using (true) always a security bug?
No. A select policy with using (true) is fine for data that is meant to be public, such as published posts or a product catalog. It is wrong for anything that belongs to one user, and on update, delete or all it is almost never intended.
Do I need a policy so my server can use the service role?
No. Supabase says a secret key authorizes access through the service_role Postgres role, "which has the bypassrls attribute". The service role ignores policies, so a policy written for it only affects the other roles it applies to.
What is the difference between using and with check?
using decides which existing rows a query can see or change. with check decides which new or updated rows are allowed. If an update or all policy has no with check, Postgres uses the using expression for both.
Does enabling RLS on a table protect it if a policy says using (true)?
No. RLS is on, but the policy lets every row through for the roles it covers. RLS only protects a table when its policies check something, such as auth.uid() against an owner column.