Row Level Security
A database feature that restricts which rows a user can read or modify based on per-row policies, enforced by the database itself rather than application code.
What is row level security?
Row level security (RLS) is a database-enforced authorization mechanism. Instead of your app checking "does this user own this row?" before every query, the database applies a policy automatically. If the policy fails, the row is invisible, as if it never existed.
In Supabase, RLS is the primary way authorization is enforced for client-side queries from the browser.
Why it matters for vibe-coded apps
Tools like Lovable, Bolt, and v0 often wire up Supabase with RLS disabled or with overly permissive policies like "auth.role() = 'authenticated'". That policy lets any logged-in user read every row from every other user.
Across FinishKit scans of AI-built Supabase apps, over 60% had at least one table with missing or broken RLS. This is the single most common way vibe-coded apps leak user data.
A typical RLS policy
create policy "Users can read their own rows"
on public.orders
for select
using ( auth.uid() = user_id );This policy means: return a row only if the authenticated user's id equals the user_id column on that row. No application code required.
How to check
- Open the Supabase SQL editor
- Run:
select tablename, rowsecurity from pg_tables where schemaname = 'public'; - Any table with
rowsecurity = falseis publicly readable by any authenticated user
Or run a FinishKit scan and RLS issues surface automatically.