VibeSecurity

Access and identity

What is Row Level Security (RLS)?

Row Level Security is a Postgres feature that decides, row by row, which records each user may read or change, using rules called policies. In Supabase it is the main protection for data reachable from the browser.

Without RLS, a table that the browser can reach is open to anyone holding your public key. With RLS turned on, the database checks a policy for every row before it answers, so a user can see only the rows the policy allows, such as their own orders.

Two things go wrong in AI-built apps. First, RLS is simply never enabled on a table the tool created. Second, RLS is enabled but the policy is written as always true, which satisfies the tool's error message while leaving the data open. Enabling RLS with no policies blocks everything from the public key, which is safe but breaks the app, so people are tempted to loosen it too far.

Enable RLS on every table in an exposed schema, then write the narrowest policy that makes the feature work, usually comparing a user id column to the signed-in user. Test each policy as a logged-out visitor and as a second, different user.

Enable RLS and let users read only their rows
alter table public.orders enable row level security;

create policy "read own orders"
on public.orders for select
to authenticated
using (auth.uid() = user_id);

Related terms

Sources

  1. 1.Supabase docs: Row Level Security
  2. 2.Supabase docs: API keys