security

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.

Also known asRLSrow-level security

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

  1. Open the Supabase SQL editor
  2. Run: select tablename, rowsecurity from pg_tables where schemaname = 'public';
  3. Any table with rowsecurity = false is publicly readable by any authenticated user

Or run a FinishKit scan and RLS issues surface automatically.

See also

Ready to ship?

Run a FinishKit scan and get a prioritized Finish Plan in minutes.

Scan your app