Views in exposed schemas run with the caller permissions (security_invoker)
Why it matters
A Postgres view runs with the privileges of the role that owns it, which on Supabase is postgres, a role that bypasses row-level security. So a view over an RLS-protected table, readable through the API, returns every row of the underlying table to anyone who can query the view: the table's policies are never consulted. The view looks like a harmless convenience ('a leaderboard', 'a dashboard summary'), and the RLS on the base table gives a false sense of safety. PostgreSQL 15 added security_invoker, which makes the view evaluate with the caller's privileges and therefore enforce the underlying RLS. Supabase's advisor flags the unsafe default as lint 0010, security definer view. AI tools generate CREATE VIEW freely and almost never add the option, so this is a common quiet bypass of an otherwise correct RLS setup.
Severity rationale
High because a definer-style view silently defeats RLS on its base tables for every API caller, but it only exposes data reachable through views that exist, which is narrower than a missing-RLS table.
Remediation
Create (or alter) every API-exposed view with security_invoker = true so the caller's RLS applies:
create or replace view public.my_open_tasks
with (security_invoker = true) as
select id, title, user_id from public.tasks where done = false;
-- or fix an existing view
alter view public.my_open_tasks set (security_invoker = true);
If a view must read data the caller cannot, put it in a non-exposed schema instead and expose a narrow, security_invoker view or a checked function. For a view over deliberately public data, add the -- INTENTIONALLY_PUBLIC: waiver line directly above CREATE VIEW with the reason.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Supabase RLS & Keys audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe:4.14 · CWE-284 — Improper Access Control
- cwe:4.14 · CWE-285 — Improper Authorization
- owasp:2021 · A01 — Broken Access Control
- external · 0010_security_definer_view — Supabase database advisor lint 0010 security definer view
Taxons
History
- 2026-10-03·v1.0.0·Initial supabase-rls-keys v1 authoring; views in exposed schemas must use security_invoker so the base-table RLS applies. Views over auth.users are covered by auth-users-not-exposed-via-view.·by supabase-rls-keys-v1-build