From e89441e40b8e3ee77bb178269065ddf415ea94c4 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Tue, 22 Sep 2026 14:40:44 -0500 Subject: [PATCH 1/7] fix: revoke excess permissions --- sql/pg_net--0.20.5--0.20.6.sql | 9 +++++++++ sql/pg_net.sql | 7 +++++-- 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 sql/pg_net--0.20.5--0.20.6.sql diff --git a/sql/pg_net--0.20.5--0.20.6.sql b/sql/pg_net--0.20.5--0.20.6.sql new file mode 100644 index 00000000..dc3e1120 --- /dev/null +++ b/sql/pg_net--0.20.5--0.20.6.sql @@ -0,0 +1,9 @@ +revoke update on all sequences in schema net to PUBLIC; + +revoke insert on all sequences in schema net to PUBLIC; +revoke update on all sequences in schema net to PUBLIC; +revoke delete on all sequences in schema net to PUBLIC; +revoke truncate on all sequences in schema net to PUBLIC; +revoke references on all sequences in schema net to PUBLIC; +revoke trigger on all sequences in schema net to PUBLIC; +revoke maintain on all sequences in schema net to PUBLIC; diff --git a/sql/pg_net.sql b/sql/pg_net.sql index b0acd86a..921dfb63 100644 --- a/sql/pg_net.sql +++ b/sql/pg_net.sql @@ -353,5 +353,8 @@ end; $$; grant usage on schema net to PUBLIC; -grant all on all sequences in schema net to PUBLIC; -grant all on all tables in schema net to PUBLIC; + +grant usage all on all sequences in schema net to PUBLIC; +grant select all on all sequences in schema net to PUBLIC; + +grant select on all tables in schema net to PUBLIC; From 65785155dcb2a35ae49ba58b84c0c398bd6cdea5 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Tue, 22 Sep 2026 15:06:40 -0500 Subject: [PATCH 2/7] fix: fix most tests --- sql/pg_net--0.20.5--0.20.6.sql | 14 +++++++------- sql/pg_net.sql | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sql/pg_net--0.20.5--0.20.6.sql b/sql/pg_net--0.20.5--0.20.6.sql index dc3e1120..1808ab12 100644 --- a/sql/pg_net--0.20.5--0.20.6.sql +++ b/sql/pg_net--0.20.5--0.20.6.sql @@ -1,9 +1,9 @@ revoke update on all sequences in schema net to PUBLIC; -revoke insert on all sequences in schema net to PUBLIC; -revoke update on all sequences in schema net to PUBLIC; -revoke delete on all sequences in schema net to PUBLIC; -revoke truncate on all sequences in schema net to PUBLIC; -revoke references on all sequences in schema net to PUBLIC; -revoke trigger on all sequences in schema net to PUBLIC; -revoke maintain on all sequences in schema net to PUBLIC; +revoke insert on all tables in schema net to PUBLIC; +revoke update on all tables in schema net to PUBLIC; +revoke delete on all tables in schema net to PUBLIC; +revoke truncate on all tables in schema net to PUBLIC; +revoke references on all tables in schema net to PUBLIC; +revoke trigger on all tables in schema net to PUBLIC; +revoke maintain on all tables in schema net to PUBLIC; diff --git a/sql/pg_net.sql b/sql/pg_net.sql index 921dfb63..b097faf5 100644 --- a/sql/pg_net.sql +++ b/sql/pg_net.sql @@ -354,7 +354,7 @@ $$; grant usage on schema net to PUBLIC; -grant usage all on all sequences in schema net to PUBLIC; -grant select all on all sequences in schema net to PUBLIC; +grant usage on all sequences in schema net to PUBLIC; +grant select on all sequences in schema net to PUBLIC; grant select on all tables in schema net to PUBLIC; From 5831c0905f142208c6eb5c8991f129259f8bd213 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Wed, 23 Sep 2026 10:42:42 -0500 Subject: [PATCH 3/7] fix: refactor test to use psycopg --- test/test_privileges.py | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/test/test_privileges.py b/test/test_privileges.py index e2b1be53..bfa4bdca 100644 --- a/test/test_privileges.py +++ b/test/test_privileges.py @@ -1,5 +1,7 @@ from sqlalchemy import text from common import collect_response_sync, http_request +import pytest +import psycopg def test_net_on_postgres_role(sess): @@ -25,34 +27,21 @@ def test_net_on_postgres_role(sess): assert response["status"] == "SUCCESS" -def test_net_on_pre_existing_role(sess): - """Check that a pre existing role can use the net schema""" +def test_net_on_pre_existing_role(conn): + """Check that a pre existing role is not able to use net schema""" - role = sess.execute(text("select current_user;")).fetchone() - assert role[0] == "postgres" + role = conn.execute("select current_user;").fetchall() + assert role[0][0] == "postgres" - sess.execute(text("set local role to pre_existing;")) - (request_id, current_user) = sess.execute( - text( - """ - select net.http_get( - 'http://localhost:8080/anything' - ), current_user; - """ + conn.execute("set local role to pre_existing;") + with pytest.raises(psycopg.errors.InsufficientPrivilege): + conn.execute( + """ + select net.http_get( + 'http://localhost:8080/anything' + ), current_user; + """ ) - ).fetchone() - assert request_id == 1 - assert current_user == "pre_existing" - - # Commit to wakeup background worker - sess.commit() - - # Confirm that the request was retrievable - sess.execute(text("set local role to pre_existing;")) - response = collect_response_sync(sess, request_id) - current_user = sess.execute(text("select current_user;")).scalar() - assert response["status"] == "SUCCESS" - assert current_user == "pre_existing" def test_net_on_new_role(sess): From ec49b0988b70888ed6659fdf3d84770492a10b06 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Wed, 23 Sep 2026 11:10:01 -0500 Subject: [PATCH 4/7] fix: fix tests, format, convert tests to psycopg --- test/test_engine.py | 2 +- test/test_privileges.py | 79 ++++++++++++++++------------------------- 2 files changed, 32 insertions(+), 49 deletions(-) diff --git a/test/test_engine.py b/test/test_engine.py index af8f1450..349e19dc 100644 --- a/test/test_engine.py +++ b/test/test_engine.py @@ -2,4 +2,4 @@ def test_connect(conn): """Sanity test verifying connection to postgres works""" conn.execute("select 1") - assert [(1, )] == conn.execute("select 1").fetchall() + assert [(1,)] == conn.execute("select 1").fetchall() diff --git a/test/test_privileges.py b/test/test_privileges.py index bfa4bdca..bc873866 100644 --- a/test/test_privileges.py +++ b/test/test_privileges.py @@ -34,9 +34,12 @@ def test_net_on_pre_existing_role(conn): assert role[0][0] == "postgres" conn.execute("set local role to pre_existing;") - with pytest.raises(psycopg.errors.InsufficientPrivilege): + with pytest.raises( + psycopg.errors.InsufficientPrivilege, + match="permission denied for table http_request_queue", + ): conn.execute( - """ + """ select net.http_get( 'http://localhost:8080/anything' ), current_user; @@ -44,57 +47,37 @@ def test_net_on_pre_existing_role(conn): ) -def test_net_on_new_role(sess): - """Check that a newly created role can use the net schema""" +def test_net_on_new_role(conn): + """Check that a newly created role cannot use the net schema""" - role = sess.execute(text("select current_user;")).fetchone() - assert role[0] == "postgres" + role = conn.execute("select current_user;").fetchall() + assert role[0][0] == "postgres" - sess.execute( - text(""" - create role another; - """) - ) - sess.execute(text("set local role to another;")) + conn.execute("create role another;") + conn.commit() + conn.execute("set local role to another;") - (request_id, current_user) = sess.execute( - text( + with pytest.raises( + psycopg.errors.InsufficientPrivilege, + match="permission denied for table http_request_queue", + ): + conn.execute( """ - select net.http_get( - 'http://localhost:8080/anything' - ), current_user; - """ + select net.http_get( + 'http://localhost:8080/anything' + ), current_user; + """ ) - ).fetchone() - assert request_id == 1 - assert current_user == "another" - - # Commit to wakeup background worker - sess.commit() - # Confirm that the request was retrievable - sess.execute(text("set local role to another;")) - response = collect_response_sync(sess, request_id) - current_user = sess.execute(text("select current_user;")).scalar() - assert response["status"] == "SUCCESS" - assert current_user == "another" + conn.rollback() - sess.execute(text("set local role to another;")) + conn.execute("set local role to another;") # can use the net.worker_restart function - (res, current_user) = sess.execute( - text( - """ - select net.worker_restart(), current_user; - """ - ) - ).fetchone() - assert res - assert current_user == "another" - - sess.execute( - text(""" - select net.wait_until_running(); - set local role postgres; - drop role another; - """) - ) + res = conn.execute("select net.worker_restart(), current_user;").fetchone() + assert res[0] + assert res[1] == "another" + + conn.execute("select net.wait_until_running();") + + conn.execute("set local role postgres;") + conn.execute("drop role another;") From 68acdec7a5b652e7c9194241e6b8307b542b51f6 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Wed, 23 Sep 2026 11:24:14 -0500 Subject: [PATCH 5/7] fix: add truncate/delete permission for single table --- sql/pg_net--0.20.5--0.20.6.sql | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/pg_net--0.20.5--0.20.6.sql b/sql/pg_net--0.20.5--0.20.6.sql index 1808ab12..06a6ca98 100644 --- a/sql/pg_net--0.20.5--0.20.6.sql +++ b/sql/pg_net--0.20.5--0.20.6.sql @@ -2,8 +2,13 @@ revoke update on all sequences in schema net to PUBLIC; revoke insert on all tables in schema net to PUBLIC; revoke update on all tables in schema net to PUBLIC; + revoke delete on all tables in schema net to PUBLIC; +grant delete on net.http_request_queue to PUBLIC; + revoke truncate on all tables in schema net to PUBLIC; +grant truncate on net.http_request_queue to PUBLIC; + revoke references on all tables in schema net to PUBLIC; revoke trigger on all tables in schema net to PUBLIC; revoke maintain on all tables in schema net to PUBLIC; From 6d895187232613fcaf82efca07073e54cf01d2dc Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Wed, 23 Sep 2026 11:26:13 -0500 Subject: [PATCH 6/7] fix: grant truncate --- sql/pg_net.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/pg_net.sql b/sql/pg_net.sql index b097faf5..01a63bc6 100644 --- a/sql/pg_net.sql +++ b/sql/pg_net.sql @@ -358,3 +358,6 @@ grant usage on all sequences in schema net to PUBLIC; grant select on all sequences in schema net to PUBLIC; grant select on all tables in schema net to PUBLIC; + +grant delete on net.http_request_queue to PUBLIC; +grant truncate on net.http_request_queue to PUBLIC; From d6231547603e57507aa12fe6e47c7190f0546d9f Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Wed, 23 Sep 2026 11:40:27 -0500 Subject: [PATCH 7/7] fix: add checks on delete/truncate --- test/test_privileges.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/test_privileges.py b/test/test_privileges.py index bc873866..9fbb4ecb 100644 --- a/test/test_privileges.py +++ b/test/test_privileges.py @@ -28,7 +28,7 @@ def test_net_on_postgres_role(sess): def test_net_on_pre_existing_role(conn): - """Check that a pre existing role is not able to use net schema""" + """Check permissions on pre-existing role""" role = conn.execute("select current_user;").fetchall() assert role[0][0] == "postgres" @@ -46,9 +46,14 @@ def test_net_on_pre_existing_role(conn): """ ) + conn.rollback() + conn.execute("set local role to pre_existing;") + conn.execute("DELETE FROM net.http_request_queue WHERE 1 = 0;") + conn.execute("TRUNCATE net.http_request_queue;") + def test_net_on_new_role(conn): - """Check that a newly created role cannot use the net schema""" + """Check permissions on newly created role""" role = conn.execute("select current_user;").fetchall() assert role[0][0] == "postgres" @@ -71,6 +76,10 @@ def test_net_on_new_role(conn): conn.rollback() + conn.execute("set local role to another;") + conn.execute("DELETE FROM net.http_request_queue WHERE 1 = 0;") + conn.execute("TRUNCATE net.http_request_queue;") + conn.execute("set local role to another;") # can use the net.worker_restart function res = conn.execute("select net.worker_restart(), current_user;").fetchone()