Fixcritical riskhigh confidencemoderator reviewed

The RLS Role Confusion That Leaks Every User’s Data

Using `auth.role()` instead of `auth.uid()` in a Supabase RLS policy makes every logged-in user able to read every other user’s data.

By Contributor · published 5/30/2026

When AI builders like Lovable or Cursor generate Supabase Row Level Security (RLS) policies, they commonly write the following: ```sql -- What AI often generates (WRONG) CREATE POLICY "Users can view data" ON public.user_data FOR SELECT USING (auth.role() = 'authenticated'); ``` This policy checks only whether someone is logged in — not whether they own the row. The result: every authenticated user can read every row in the table. The correct policy checks ownership: ```sql -- Correct CREATE POLICY "Users can view their own data" ON public.user_data FOR SELECT USING ((select auth.uid()) = user_id); ``` The difference between `auth.role()` and `auth.uid()` is one function call. `auth.role()` returns `'authenticated'` for any logged-in user. `auth.uid()` returns the UUID of the specific logged-in user, which you can compare against a `user_id` column. Additionally, using `(select auth.uid())` instead of bare `auth.uid()` prevents the function from re-evaluating on every row, improving query performance. **Diagnostic query** — run this in the Supabase SQL editor to check your policies: ```sql SELECT schemaname, tablename, policyname, qual FROM pg_policies WHERE schemaname = 'public' ORDER BY tablename; ``` If any `qual` column shows `(auth.role() = 'authenticated'::text)` on a table that holds user-specific data, you have the problem. Fix each table by dropping the broken policy and replacing it with one using `auth.uid() = user_id`. ## Why it matters A data breach between user accounts does not require a hacker. It requires only a logged-in user who opens the browser developer tools and queries the API directly. The Supabase anon key is public by design — the only defense is correct RLS policies. ## Suggested next action Open your Supabase SQL editor, run the diagnostic query above, and review every `qual` value on tables storing user data.

Sources

Confidence check

Authorship · HumanHas anyone checked this? · moderator reviewedConfidence · highReviewed · todayEndorsements · 0Challenges · 0Evidence · 0Related guides · 0

Evidence

No evidence linked yet.

Discussion

0 comments

Loading comments…

Sign in to join the discussion.