Skip to content

[2.1.0] Require USAGE on plpgsql to use a plx language - #15

Open
OffgridwithJD wants to merge 1 commit into
commandprompt:masterfrom
OffgridwithJD:feat/plpgsql-usage-gate
Open

OffgridwithJD wants to merge 1 commit into
commandprompt:masterfrom
OffgridwithJD:feat/plpgsql-usage-gate

Conversation

@OffgridwithJD

Copy link
Copy Markdown

Summary

A plx function is stored and executed as plpgsql, but plx only checked USAGE on its own language. After REVOKE USAGE ON LANGUAGE plpgsql FROM PUBLIC, a role could still write plpgsql in two ways:

  • DO LANGUAGE plxplsql $$ ... $$
  • a body that already carries the /*plx:v1: header, which is stored without transpiling

The validator (CREATE FUNCTION) and the inline handler (DO) now also require USAGE on plpgsql. Otherwise they fail with:

ERROR:  permission denied for language plpgsql
DETAIL:  Language plxruby is executed as plpgsql, so using it requires USAGE on plpgsql.

This matches plpgsql's own rules:

  • The check happens at creation and for DO blocks.
  • Functions that already exist keep running after a REVOKE.
  • Superusers pass as usual.

The validator checks before the sentinel test, so pre-transpiled bodies are gated too. Builds against PG 13–15 (pg_language_aclcheck) and 16+ (object_aclcheck).

Independent of #12 to #14. It touches only plx_core.c, plus a new plx_privileges suite. Once this merges, the security section in #13 can say that revoking plpgsql is enough, instead of telling users to revoke both.

Testing

  • New plx_privileges suite covers the granted case, CREATE FUNCTION and DO denied after the REVOKE, the sentinel body denied, an existing function still running, and superusers unaffected.
  • make installcheck: all 14 suites pass on PG 18.4.
  • make differentialcheck passes.

🤖 Generated with Claude Code

A plx function is stored and executed as plpgsql, so a role with USAGE on
a plx language could create plpgsql functions and run DO blocks even
after USAGE on plpgsql was revoked from it. The validator and the inline
handler now also check USAGE on plpgsql, at the same points plpgsql checks
its own: function creation and DO. The validator checks before the
sentinel test, so a body that already carries the transpiled header is
gated too. Existing functions keep running, as with plpgsql.

New regression suite plx_privileges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@jdatcmd jdatcmd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adversarial review. Tested on PostgreSQL 18.4: builds without warnings, and make installcheck passes 14/14.

I tried to get past the gate as a role with no USAGE on plpgsql. Every attempt was denied with permission denied for language plpgsql:

  • SET check_function_bodies = off, then CREATE FUNCTION with a body that already carries the /*plx:v1: header
  • CREATE PROCEDURE ... LANGUAGE plxruby
  • DO LANGUAGE plxtsql

A role granted USAGE on plpgsql directly (not through PUBLIC) can still create and run plx functions.

Approving. Two notes:

  • CI has not run yet (fork run waiting for approval). The PostgreSQL 13 to 15 branch (pg_language_aclcheck) has not been compiled anywhere I can see, so please make sure that run passes before merging.
  • This changes behaviour for a site that revoked plpgsql on purpose and kept the plx languages for its users: those users lose access. The CHANGELOG heading "Revoking plpgsql now revokes plx" covers it. Worth repeating in the release notes.

@OffgridwithJD OffgridwithJD changed the title Require USAGE on plpgsql to use a plx language [2.1.0] Require USAGE on plpgsql to use a plx language Nov 9, 2026
@OffgridwithJD

Copy link
Copy Markdown
Author

Thanks. On the CI note: the fork run for 6d1dfa2 has since been approved and passed on PostgreSQL 13, 14, 15, 16, 17 and 18. So the pg_language_aclcheck branch compiled and the suite passed on 13 to 15.

On the release notes: agreed. The 2.1.0 release PR will repeat that a site which revoked plpgsql but kept the plx languages for its users loses plx for those users.

🤖 Generated with Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants