Skip to content

Commit ef2d7c6

Browse files
committed
Doc: word-smith the discussion of secure schema usage patterns.
Rearrange the discussion of user-private schemas so that details applying only to upgraded-from-pre-v15 databases are in a follow-on paragraph, not in the main description of how to set up this pattern. This seems a little clearer even today, and it'll get more so as pre-v15 systems fade into the sunset. Wording contributions from Robert Haas, Tom Lane, Noah Misch. Discussion: https://postgr.es/m/CA+TgmoYUHsfp90inEMAP0yNr7Y_L6EphPH1YOon1JKtBztXHyQ@mail.gmail.com
1 parent 1dd6700 commit ef2d7c6

File tree

1 file changed

+28
-25
lines changed

1 file changed

+28
-25
lines changed

doc/src/sgml/ddl.sgml

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,40 +3211,43 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
32113211
query that database would take protective action at the beginning of each
32123212
session. Specifically, they would begin each session by
32133213
setting <varname>search_path</varname> to the empty string or otherwise
3214-
removing non-superuser-writable schemas
3214+
removing schemas that are writable by non-superusers
32153215
from <varname>search_path</varname>. There are a few usage patterns
32163216
easily supported by the default configuration:
32173217
<itemizedlist>
32183218
<listitem>
3219-
<!-- "DROP SCHEMA public" is inferior to this REVOKE, because pg_dump
3220-
doesn't preserve that DROP.
3221-
3222-
A database owner can attack the database's users via "CREATE SCHEMA
3219+
<para>
3220+
Constrain ordinary users to user-private schemas.
3221+
To implement this pattern, first ensure that no schemas have
3222+
public <literal>CREATE</literal> privileges. Then, for every user
3223+
needing to create non-temporary objects, create a schema with the
3224+
same name as that user, for example
3225+
<literal>CREATE SCHEMA alice AUTHORIZATION alice</literal>.
3226+
(Recall that the default search path starts
3227+
with <literal>$user</literal>, which resolves to the user
3228+
name. Therefore, if each user has a separate schema, they access
3229+
their own schemas by default.) This pattern is a secure schema
3230+
usage pattern unless an untrusted user is the database owner or
3231+
holds the <literal>CREATEROLE</literal> privilege, in which case no
3232+
secure schema usage pattern exists.
3233+
</para>
3234+
<!-- A database owner can attack the database's users via "CREATE SCHEMA
32233235
trojan; ALTER DATABASE $mydb SET search_path = trojan, public;". A
32243236
CREATEROLE user can issue "GRANT $dbowner TO $me" and then use the
32253237
database owner attack. -->
3238+
32263239
<para>
3227-
Constrain ordinary users to user-private schemas. To implement this,
3228-
first issue <literal>REVOKE CREATE ON SCHEMA public FROM
3229-
PUBLIC</literal>. Then, for every user needing to create non-temporary
3230-
objects, create a schema with the same name as that user. Recall that
3231-
the default search path starts with <literal>$user</literal>, which
3232-
resolves to the user name. Therefore, if each user has a separate
3233-
schema, they access their own schemas by default. After adopting this
3234-
pattern in a database where untrusted users had already logged in,
3235-
consider auditing the public schema for objects named like objects in
3236-
schema <literal>pg_catalog</literal>. This pattern is a secure schema
3237-
usage pattern unless an untrusted user is the database owner or holds
3238-
the <literal>CREATEROLE</literal> privilege, in which case no secure
3239-
schema usage pattern exists.
3240-
</para>
3241-
<para>
3242-
If the database originated in an upgrade
3243-
from <productname>PostgreSQL</productname> 14 or earlier,
3244-
the <literal>REVOKE</literal> is essential. Otherwise, the default
3245-
configuration follows this pattern; ordinary users can create only
3246-
temporary objects until a privileged user furnishes a schema.
3240+
In <productname>PostgreSQL</productname> 15 and later, the default
3241+
configuration supports this usage pattern. In prior versions, or
3242+
when using a database that has been upgraded from a prior version,
3243+
you will need to remove the public <literal>CREATE</literal>
3244+
privilege from the <literal>public</literal> schema (issue
3245+
<literal>REVOKE CREATE ON SCHEMA public FROM PUBLIC</literal>).
3246+
Then consider auditing the <literal>public</literal> schema for
3247+
objects named like objects in schema <literal>pg_catalog</literal>.
32473248
</para>
3249+
<!-- "DROP SCHEMA public" is inferior to this REVOKE, because pg_dump
3250+
doesn't preserve that DROP. -->
32483251
</listitem>
32493252

32503253
<listitem>

0 commit comments

Comments
 (0)