Skip to content

fix: revoke public trigger privilege on net tables#259

Closed
samrose wants to merge 4 commits into
masterfrom
fix/revoke-public-trigger-privilege
Closed

fix: revoke public trigger privilege on net tables#259
samrose wants to merge 4 commits into
masterfrom
fix/revoke-public-trigger-privilege

Conversation

@samrose

@samrose samrose commented Jul 1, 2026

Copy link
Copy Markdown

Summary

This fixes a privilege escalation issue caused by granting ALL table privileges on pg_net internal tables to PUBLIC.

ALL includes TRIGGER, which allowed ordinary roles to create triggers on net._http_response.

Changes

  • Replace grant all on all tables in schema net to PUBLIC with an explicit grant list that excludes TRIGGER.
  • Add an upgrade script from 0.20.3 to 0.20.4 that revokes TRIGGER on all tables in the net schema from PUBLIC.
  • Bump the extension version to 0.20.4.
  • Add a regression test confirming ordinary roles cannot create triggers on net._http_response.

The previous broad grant was intended to let non-postgres roles use pg_net after the SQL functions were changed to security invoker. That behavior should be preserved.

The minimal safe fix is to remove only the TRIGGER privilege while keeping the table privileges needed for normal pg_net operation.

Testing

nix develop -c xpg test

Result:

63 passed in 92.65s (0:01:32)

Focused regression check:

env PYTEST_ADDOPTS='test/test_privileges.py -k test_public_roles_cannot_create_triggers_on_internal_tables' nix develop -c xpg test

Result:

1 passed, 3 deselected

@brainrake brainrake left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks like it does what the issue describes and fixes the problem. Also does version bump same as last one.
There may be consequences I am unaware of.

Comment thread sql/pg_net.sql Outdated

@imor imor 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.

@samrose left a couple of comments for improvements, otherwise LGTM. Approved to unblock you.

Comment thread sql/pg_net.sql Outdated
Comment thread test/test_privileges.py Outdated
imor added 2 commits July 2, 2026 18:28
Make test assertions more explicit and checking for all tables in pg_net.
@imor
imor requested a review from hanefi July 2, 2026 13:15
@imor

imor commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

I'm taking over this bug fix from @samrose and have pushed a couple of commits. @hanefi, @za-arthur could you please do a final review before I merge it?

Comment thread sql/pg_net.sql Outdated

@steve-chavez steve-chavez left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just to make it clear, the vulnerability here doesn't have anything to do with SECURITY definer functions.

Regular INVOKER functions have the same problem because they're using the worker which uses the "initdb-created superuser" by default to execute the functions; but this can be changed with pg_net.username.

I'm not sure if this is the right fix because some users have claimed to use TRIGGER functions on the net tables so we would be causing a breaking change.

@imor

imor commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

That's a much better alternative suggested by @steve-chavez. Basically we set pg_net.username to a non-superuser role like postgres and the worker runs the sql as that user, entirely shutting down the privilege escalation vector: now the triggers would run as the postgres user. Not to mention that triggers are a valid API surface we support. Since the main fix for this should be done in supabase/postgres:

  • @steve-chavez I'm thinking of changing the scope of this PR to add a test confirming that triggers indeed run as the pg_net.username user.
  • @samrose could you please point me to the code where pg_net.username GUC can be set in supabase/postgres, I can open a PR in that repo.

@steve-chavez

Copy link
Copy Markdown
Member

I'm thinking of changing the scope of this PR to add a test confirming that triggers indeed run as the pg_net.username user.

Sounds good to me.

@samrose

samrose commented Jul 3, 2026

Copy link
Copy Markdown
Author

sounds good to me to thanks @steve-chavez and @imor

@samrose samrose closed this Jul 3, 2026
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.

6 participants