Repository navigation
[2.1.0] Require USAGE on plpgsql to use a plx language - #15
OffgridwithJD wants to merge 1 commit into
Conversation
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
left a comment
There was a problem hiding this comment.
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, thenCREATE FUNCTIONwith a body that already carries the/*plx:v1:headerCREATE PROCEDURE ... LANGUAGE plxrubyDO 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.
|
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 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 |
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 $$ ... $$/*plx:v1:header, which is stored without transpilingThe validator (
CREATE FUNCTION) and the inline handler (DO) now also require USAGE on plpgsql. Otherwise they fail with:This matches plpgsql's own rules:
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 newplx_privilegessuite. Once this merges, the security section in #13 can say that revoking plpgsql is enough, instead of telling users to revoke both.Testing
plx_privilegessuite 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 differentialcheckpasses.🤖 Generated with Claude Code