· 11 min read
The RLS Trap That Passes Every Test: A Postgres View Runs as Its Definer Unless You Say Otherwise
A Postgres view executes with its definer's privileges unless security_invoker is set, and that setting is off by default. Every view created before somebody thought about row-level security is therefore in the wrong mode, and the usual test, that a user sees their own data, passes identically in both modes. This explains the semantics, the migration problem, and the audit query that tells you which of your views are routing around the policy.