@ -3001,20 +3001,18 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
<para>
<para>
By default, users cannot access any objects in schemas they do not
By default, users cannot access any objects in schemas they do not
own. To allow that, the owner of the schema must grant the
own. To allow that, the owner of the schema must grant the
<literal>USAGE</literal> privilege on the schema. To allow users
<literal>USAGE</literal> privilege on the schema. By default, everyone
to make use of the objects in the schema, additional privileges
has that privilege on the schema <literal>public</literal>. To allow
might need to be granted, as appropriate for the object.
users to make use of the objects in a schema, additional privileges might
need to be granted, as appropriate for the object.
</para>
</para>
<para>
<para>
A user can also be allowed to create objects in someone else's
A user can also be allowed to create objects in someone else's schema. To
schema. To allow that, the <literal>CREATE</literal> privilege on
allow that, the <literal>CREATE</literal> privilege on the schema needs to
the schema needs to be granted. Note that by default, everyone
be granted. In databases upgraded from
has <literal>CREATE</literal> and <literal>USAGE</literal> privileges on
<productname>PostgreSQL</productname> 14 or earlier, everyone has that
the schema
privilege on the schema <literal>public</literal>.
<literal>public</literal>. This allows all users that are able to
connect to a given database to create objects in its
<literal>public</literal> schema.
Some <link linkend="ddl-schemas-patterns">usage patterns</link> call for
Some <link linkend="ddl-schemas-patterns">usage patterns</link> call for
revoking that privilege:
revoking that privilege:
<programlisting>
<programlisting>
@ -3087,20 +3085,25 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
database owner attack. -->
database owner attack. -->
<para>
<para>
Constrain ordinary users to user-private schemas. To implement this,
Constrain ordinary users to user-private schemas. To implement this,
issue <literal>REVOKE CREATE ON SCHEMA public FROM PUBLIC</literal>,
first issue <literal>REVOKE CREATE ON SCHEMA public FROM
and create a schema for each user with the same name as that user.
PUBLIC</literal>. Then, for every user needing to create non-temporary
Recall that the default search path starts
objects, create a schema with the same name as that user. Recall that
with <literal>$user</literal>, which resolves to the user name.
the default search path starts with <literal>$user</literal>, which
Therefore, if each user has a separate schema, they access their own
resolves to the user name. Therefore, if each user has a separate
schemas by default. After adopting this pattern in a database where
schema, they access their own schema s by default. After adopting this
untrusted users had already logged in, consider auditing the public
pattern in a database where untrusted users had already logged in,
schema for objects named like objects in
consider auditing the public schema for objects named like objects in
schema <literal>pg_catalog</literal>. This pattern is a secure schema
schema <literal>pg_catalog</literal>. This pattern is a secure schema
usage pattern unless an untrusted user is the database owner or holds
usage pattern unless an untrusted user is the database owner or holds
the <literal>CREATEROLE</literal> privilege, in which case no secure
the <literal>CREATEROLE</literal> privilege, in which case no secure
schema usage pattern exists.
schema usage pattern exists.
</para>
</para>
<para>
<para>
If the database originated in an upgrade
from <productname>PostgreSQL</productname> 14 or earlier,
the <literal>REVOKE</literal> is essential. Otherwise, the default
configuration follows this pattern; ordinary users can create only
temporary objects until a privileged user furnishes a schema.
</para>
</para>
</listitem>
</listitem>
@ -3109,10 +3112,10 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
Remove the public schema from the default search path, by modifying
Remove the public schema from the default search path, by modifying
<link linkend="config-setting-configuration-file"><filename>postgresql.conf</filename></link>
<link linkend="config-setting-configuration-file"><filename>postgresql.conf</filename></link>
or by issuing <literal>ALTER ROLE ALL SET search_path =
or by issuing <literal>ALTER ROLE ALL SET search_path =
"$user"</literal>. Everyone retains the ability to create objects in
"$user"</literal>. Then, grant privileges to create in the public
the public schema, but only qualified names will choose those objects.
schema. Only qualified names will choose public schema objects. While
While qualified table references are fine, calls to functions in the
qualified table references are fine, calls to functions in the public
public schema <link linkend="typeconv-func">will be unsafe or
schema <link linkend="typeconv-func">will be unsafe or
unreliable</link>. If you create functions or extensions in the public
unreliable</link>. If you create functions or extensions in the public
schema, use the first pattern instead. Otherwise, like the first
schema, use the first pattern instead. Otherwise, like the first
pattern, this is secure unless an untrusted user is the database owner
pattern, this is secure unless an untrusted user is the database owner
@ -3122,11 +3125,14 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
<listitem>
<listitem>
<para>
<para>
Keep the default. All users access the public schema implicitly. This
Keep the default search path, and grant privileges to create in the
public schema. All users access the public schema implicitly. This
simulates the situation where schemas are not available at all, giving
simulates the situation where schemas are not available at all, giving
a smooth transition from the non-schema-aware world. However, this is
a smooth transition from the non-schema-aware world. However, this is
never a secure pattern. It is acceptable only when the database has a
never a secure pattern. It is acceptable only when the database has a
single user or a few mutually-trusting users.
single user or a few mutually-trusting users. In databases upgraded
from <productname>PostgreSQL</productname> 14 or earlier, this is the
default.
</para>
</para>
</listitem>
</listitem>
</itemizedlist>
</itemizedlist>