Demo, all content is generated
Question

My view shows draft posts to people who aren't logged in

Solved · 1763 views · asked by ngozi_c · edited

I made a view posts_with_author that joins posts and profiles so my feed is one query. Posts have RLS so only published posts are visible to others. But when I query the view logged out, I get drafts too! How can a view ignore RLS?

What I’ve tried

Double checked the policy on posts, querying posts directly as anon only gives published ones. Added a policy on the view but Supabase says views can't have policies.

Comment
Is the view created by you in the SQL editor? Then I know what it is. mira_dev · edited

2 answers

Marked as helpful by the asker
mira_dev · edited

By default a Postgres view runs with the permissions of its owner, and in Supabase that's postgres, which bypasses RLS. So your view reads the tables as a superuser.

On Postgres 15+ (all current Supabase projects) you can make it respect the caller's RLS:

alter view public.posts_with_author set (security_invoker = true);

Better, create it that way in the migration, and repeat the with part whenever you recreate it:

create or replace view public.posts_with_author
with (security_invoker = true) as
select p.*, pr.display_name
from posts p join profiles pr on pr.id = p.author_id;

The Security Advisor flags these as security_definer_view. Worth checking for others.

Comment
Fixed and the advisor found a second one I forgot about. Scary. ngozi_c · edited
Remember profiles now also needs a select policy for anon, or the join will drop every row for logged-out visitors. hannah_reyes · edited
postgres_pete · edited

Worth also doing revoke select on public.posts_with_author from anon; if logged-out visitors never need the view. Belt and braces.

Comment