Thread: Why is EXECUTE granted to PUBLIC for all routines?

Why is EXECUTE granted to PUBLIC for all routines?

From
Jacek Trocinski
Date:
Hi,

The default behavior on Postgres is to grant EXECUTE to PUBLIC on any
function or procedure that is created.

I feel this this is a security concern, especially for procedures and
functions defined with the "SECURITY DEFINER" clause.

Normally, we don’t want everyone on the database to be able to run
procedures or function without explicitly granting them the privilege
to do so.

Is there any reason to keep grant EXECUTE to PUBLIC on routines as the default?

Best,
Jacek Trocinski



Re: Why is EXECUTE granted to PUBLIC for all routines?

From
Tom Lane
Date:
Jacek Trocinski <jacek@hedgehog.app> writes:
> The default behavior on Postgres is to grant EXECUTE to PUBLIC on any
> function or procedure that is created.

> I feel this this is a security concern, especially for procedures and
> functions defined with the "SECURITY DEFINER" clause.

There is zero security concern for non-SECURITY-DEFINER functions,
since they do nothing callers couldn't do for themselves.  For those,
you typically do want to grant out permissions.  As for SECURITY DEFINER
functions, there is no reason to make one unless it is meant to be called
by someone besides the owner.  Perhaps PUBLIC isn't the scope you want to
grant it to, but no-privileges wouldn't be a useful default there either.

In any case, changing this decision now would cause lots of problems,
such as breaking existing dump files.  We're unlikely to revisit it.

As noted in the docs, best practice is to adjust the permissions
as you want them in the same transaction that creates the function.

            regards, tom lane



Re: Why is EXECUTE granted to PUBLIC for all routines?

From
Isaac Morland
Date:
On Fri, 22 Apr 2022 at 13:44, Tom Lane <tgl@sss.pgh.pa.us> wrote:
 
There is zero security concern for non-SECURITY-DEFINER functions,
since they do nothing callers couldn't do for themselves.  For those,
you typically do want to grant out permissions.  As for SECURITY DEFINER
functions, there is no reason to make one unless it is meant to be called
by someone besides the owner.  Perhaps PUBLIC isn't the scope you want to
grant it to, but no-privileges wouldn't be a useful default there either.

No privileges would be a safe default, not entirely unlike the default "can only connect from localhost" pg_hba.conf, … 
 
In any case, changing this decision now would cause lots of problems,
such as breaking existing dump files.  We're unlikely to revisit it.

… but, yeah, this would be rather hard to change without causing more trouble.
 
As noted in the docs, best practice is to adjust the permissions
as you want them in the same transaction that creates the function.

I wrote a function which resets the permissions on all objects in the specified schemas to default. Then for each project I have a privileges-granting file which starts by resetting all permissions, then grants exactly the permissions I want. Most of the resetting is done by checking the existing privileges and revoking them; then it ASSERTs that this leaves an empty ACL, and finally does an UPDATE on the relevant system table to change the ACL from empty to NULL. For SECURITY DEFINER functions, the reset function then revokes PUBLIC privileges, leaving it to the specific project to grant the appropriate privileges.

BTW, the reg* types are amazing for writing this kind of stuff. Makes all sorts of things so much easier.