Thread
-
Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
Steve Chavez <steve@supabase.io> — 2026-01-27T16:36:51Z
Hello hackers, Currently views are not secure by default since they bypass RLS. PostgreSQL 15 introduced the `WITH (security_invoker = true)` option for this but it's easy to miss on every new view created. It's also inconsistent with functions, which default to SECURITY INVOKER. I propose adding an option: `CREATE DATABASE .. SECURITY_INVOKER_VIEWS <bool>` (false by default to maintain backwards compat), so a database will have newly created views as SECURITY INVOKER. Let me know what you think. Best regards, Steve Chavez
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
Laurenz Albe <laurenz.albe@cybertec.at> — 2026-01-27T17:21:11Z
On Tue, 2026-01-27 at 11:36 -0500, Steve Chavez wrote: > Currently views are not secure by default since they bypass RLS. PostgreSQL 15 introduced the > `WITH (security_invoker = true)` option for this but it's easy to miss on every new view created. > > It's also inconsistent with functions, which default to SECURITY INVOKER. > > I propose adding an option: `CREATE DATABASE .. SECURITY_INVOKER_VIEWS <bool>` (false by default > to maintain backwards compat), so a database will have newly created views as SECURITY INVOKER. > > Let me know what you think. I don't like it. First of all, such a setting won't guarantee that all views get created with "security_invoker" set - the user is still free to explicitly set "security_invoker = off". Second, and more importantly, that is a setting that changes the behavior of SQL statements, which is something that the project has learned to fear. It is problematic if the same SQL statement has different semantics with different settings. If somebody runs a DDL script in a database created with SECURITY_INVOKER_VIEWS TRUE, it could happen that the resulting schema causes unexpected "permission denied" errors in the application. Yours, Laurenz Albe
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
Steve Chavez <steve@supabase.io> — 2026-01-27T17:46:41Z
Hi Laurenz, > First of all, such a setting won't guarantee that all views get created with "security_invoker" set - the user is still free to explicitly set "security_invoker = off" Yes, but that would be a conscious decision. The idea is to provide a sane default. > If somebody runs a DDL script in a database created with SECURITY_INVOKER_VIEWS TRUE, it could happen that the resulting schema causes unexpected "permission denied" errors in the application. IMO that's much better than leaking information by default, which views do with security_definer. One problem is that it could indeed be confusing if an ALTER DATABASE modified SECURITY_INVOKER_VIEWS and then all queries start failing. So one enhancement could be to only allow SECURITY_INVOKER_VIEWS at creation time, like with the LOCALE option. Best regards, Steve Chavez On Tue, 27 Jan 2026 at 12:21, Laurenz Albe <laurenz.albe@cybertec.at> wrote: > On Tue, 2026-01-27 at 11:36 -0500, Steve Chavez wrote: > > Currently views are not secure by default since they bypass RLS. > PostgreSQL 15 introduced the > > `WITH (security_invoker = true)` option for this but it's easy to miss > on every new view created. > > > > It's also inconsistent with functions, which default to SECURITY INVOKER. > > > > I propose adding an option: `CREATE DATABASE .. SECURITY_INVOKER_VIEWS > <bool>` (false by default > > to maintain backwards compat), so a database will have newly created > views as SECURITY INVOKER. > > > > Let me know what you think. > > I don't like it. > > First of all, such a setting won't guarantee that all views get created > with "security_invoker" > set - the user is still free to explicitly set "security_invoker = off". > > Second, and more importantly, that is a setting that changes the behavior > of SQL statements, > which is something that the project has learned to fear. It is > problematic if the same SQL > statement has different semantics with different settings. If somebody > runs a DDL script in > a database created with SECURITY_INVOKER_VIEWS TRUE, it could happen that > the resulting schema > causes unexpected "permission denied" errors in the application. > > Yours, > Laurenz Albe >
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
David G. Johnston <david.g.johnston@gmail.com> — 2026-01-27T18:02:34Z
On Tuesday, January 27, 2026, Steve Chavez <steve@supabase.io> wrote: > Hello hackers, > > Currently views are not secure by default since they bypass RLS. > PostgreSQL 15 introduced the `WITH (security_invoker = true)` option for > this but it's easy to miss on every new view created. > > It's also inconsistent with functions, which default to SECURITY INVOKER. > I’d be more inclined to change this incompatibility than try to affect action at a distance with a database setting. But suspect the status-quo is likely to prevail. Maybe we need a view of views that reference RLS relations that aren’t security_invoker? Add something to the docs? If one knows enough to enable a database setting they can institute different less problematic solutions as well. Maybe we provide an event trigger example. David J.
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
Laurenz Albe <laurenz.albe@cybertec.at> — 2026-01-27T19:12:34Z
On Tue, 2026-01-27 at 12:46 -0500, Steve Chavez wrote: > > If somebody runs a DDL script in > > a database created with SECURITY_INVOKER_VIEWS TRUE, it could happen that the resulting schema > > causes unexpected "permission denied" errors in the application. > > IMO that's much better than leaking information by default, which views do with security_definer. That's what you think. Other people who use views with "security_barrier = on" to allow unprivileged users a restricted view on confidential data would be very unhappy indeed if their CREATE VIEW statements would suddenly create views that give the users an unexpected "permisson denied". You might argue that they should set "security_invoker = off" explicitly if they want to be sure that that cannot happen, but then I'm going to answer that the same applies to your use case. > One problem is that it could indeed be confusing if an ALTER DATABASE modified SECURITY_INVOKER_VIEWS and then all queries start failing. > So one enhancement could be to only allow SECURITY_INVOKER_VIEWS at creation time, like with the LOCALE option. I am slightly confused. I had understood your proposal to be that SECURITY_INVOKER_VIEWS only applies at CREATE VIEW time anyway. If you want the setting to override any "security_invoker" setting on existing views, I like that even less, because it would prevent people from explicitly opting out (unless you propose to change "security_invoker" into a ternary setting with values "on", "off" and "unset"). Yours, Laurenz Albe
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
Steve Chavez <steve@supabase.io> — 2026-01-28T19:19:31Z
Hi David, Laurenz, > Other people who use views with "security_barrier = on" CMIIW, but wasn't security_barrier a mechanism to do RLS before actual RLS (policies) were introduced? So in a way aren't they superseded by RLS? > I’d be more inclined to change this incompatibility than try to affect action at a distance with a database setting. Could we instead have a shortcut for view creation like `CREATE SECURE VIEW` (would be the same as WITH (security_invoker = true)`) ? This at least makes it harder to forget specifying the option and also denotes that by default views are insecure (since they're most likely created by security_definer=superuser) Best regards, Steve On Tue, 27 Jan 2026 at 14:12, Laurenz Albe <laurenz.albe@cybertec.at> wrote: > On Tue, 2026-01-27 at 12:46 -0500, Steve Chavez wrote: > > > If somebody runs a DDL script in > > > a database created with SECURITY_INVOKER_VIEWS TRUE, it could happen > that the resulting schema > > > causes unexpected "permission denied" errors in the application. > > > > IMO that's much better than leaking information by default, which views > do with security_definer. > > That's what you think. Other people who use views with "security_barrier > = on" to allow > unprivileged users a restricted view on confidential data would be very > unhappy indeed if > their CREATE VIEW statements would suddenly create views that give the > users an unexpected > "permisson denied". > > You might argue that they should set "security_invoker = off" explicitly > if they want to > be sure that that cannot happen, but then I'm going to answer that the > same applies to your > use case. > > > One problem is that it could indeed be confusing if an ALTER DATABASE > modified SECURITY_INVOKER_VIEWS and then all queries start failing. > > So one enhancement could be to only allow SECURITY_INVOKER_VIEWS at > creation time, like with the LOCALE option. > > I am slightly confused. I had understood your proposal to be that > SECURITY_INVOKER_VIEWS only > applies at CREATE VIEW time anyway. If you want the setting to override > any "security_invoker" > setting on existing views, I like that even less, because it would prevent > people from > explicitly opting out (unless you propose to change "security_invoker" > into a ternary setting > with values "on", "off" and "unset"). > > Yours, > Laurenz Albe >
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
David G. Johnston <david.g.johnston@gmail.com> — 2026-01-28T19:39:18Z
On Wed, Jan 28, 2026 at 12:19 PM Steve Chavez <steve@supabase.io> wrote: > > I’d be more inclined to change this incompatibility than try to affect > action at a distance with a database setting. > > Could we instead have a shortcut for view creation like `CREATE SECURE > VIEW` (would be the same as WITH (security_invoker = true)`) ? This at > least makes it harder to forget specifying the option and also denotes that > by default views are insecure (since they're most likely created by > security_definer=superuser) > > Please don't top-post. Inventing alternative syntax with the same fundamental issue, just an arguably different failure threshold, is unappealing. David J.
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
Laurenz Albe <laurenz.albe@cybertec.at> — 2026-01-28T20:28:43Z
On Wed, 2026-01-28 at 14:19 -0500, Steve Chavez wrote: > CMIIW, but wasn't security_barrier a mechanism to do RLS before actual RLS (policies) were introduced? So in a way aren't they superseded by RLS? I wouldn't say so. Creating a view that allows a user to see only certain columns of a table is something quite different from restricting the rows a user can operate on. Yours, Laurenz Albe
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
Steve Chavez <steve@supabase.io> — 2026-01-28T20:43:54Z
But that is a property of just regular views not necessarily security_barrier right? i.e. "to be able to hide certain columns". > Please don't top-post. My bad, to be honest I don't understand how I can reply to different paragraphs in a more structured way. Are there guidelines/examples on the pg docs about this rule? Best regards, Steve On Wed, 28 Jan 2026 at 15:28, Laurenz Albe <laurenz.albe@cybertec.at> wrote: > On Wed, 2026-01-28 at 14:19 -0500, Steve Chavez wrote: > > CMIIW, but wasn't security_barrier a mechanism to do RLS before actual > RLS (policies) were introduced? So in a way aren't they superseded by RLS? > > I wouldn't say so. > > Creating a view that allows a user to see only certain columns of a table > is something quite different from restricting the rows a user can operate > on. > > Yours, > Laurenz Albe >
-
Re: Add SECURITY_INVOKER_VIEWS option to CREATE DATABASE
Laurenz Albe <laurenz.albe@cybertec.at> — 2026-01-29T06:25:10Z
On Wed, 2026-01-28 at 15:43 -0500, Steve Chavez wrote: > But that is a property of just regular views not necessarily security_barrier right? i.e. "to be able to hide certain columns". Right, but without "security_barries = on" it may be that a sneaky attacker can subvert the security. With that setting, only LEAKPROOF functions and operators are can be pushed into the view definition. But we are getting off-topic. My point is that your proposed database setting would change the behavior of such a view so that it wouldn't work any more. Yours, Laurenz Albe