Skip to content

Revoking access to pg_net objects has no effect: no privileges could be revoked

Last edited: 10/6/2026

When you run revoke on the net schema or its objects as the postgres role, the statement completes but access stays the same. Postgres prints a warning instead of an error:

WARNING: no privileges could be revoked for "net"

The same warning appears for http_request_queue, _http_response, and the net.http_* functions. A grant on these objects prints no privileges were granted. The SQL Editor doesn't display warnings, so the statement looks successful there.

Check which roles have access#

To list the privileges on the net schema and its tables, and the role that granted each one, run the following in the SQL Editor:

select
'schema net' as object,
case acl.grantee when 0 then 'PUBLIC' else acl.grantee::regrole::text end as grantee,
acl.grantor::regrole as grantor,
acl.privilege_type
from pg_namespace n
cross join lateral aclexplode(n.nspacl) as acl
where n.nspname = 'net'
union all
select
c.relname,
case acl.grantee when 0 then 'PUBLIC' else acl.grantee::regrole::text end,
acl.grantor::regrole,
acl.privilege_type
from pg_class c
cross join lateral aclexplode(c.relacl) as acl
where c.relnamespace = 'net'::regnamespace
order by 1, 2, 4;

Every row has supabase_admin as the grantor. To check what one role can do, replace my_role and run:

select
has_schema_privilege('my_role', 'net', 'usage') as schema_usage,
has_table_privilege('my_role', 'net.http_request_queue', 'select') as read_queue,
has_function_privilege(
'my_role',
'net.http_post(text, jsonb, jsonb, jsonb, integer)',
'execute'
) as call_http_post;

Why the revoke has no effect#

Supabase creates the pg_net extension as the supabase_admin role, so supabase_admin owns the net schema and everything in it. In Postgres, a role can revoke only the privileges that it granted. For more information, see the Postgres documentation on REVOKE.

The extension grants usage on the schema and all privileges on its tables and sequences to PUBLIC. On most projects, its functions are also executable by PUBLIC, which is the Postgres default for functions. For the projects where they aren't, see Which roles can use pg_net. When the extension is created, Supabase also grants usage on net to postgres, anon, authenticated, and service_role.

The postgres role made none of these grants, so its revoke finds nothing to remove. It holds the privileges without the grant option, so its grant to another role does nothing either, and Postgres reports no privileges were granted.

A grant to PUBLIC applies to every role, including roles you create later. Postgres has no way to exclude a single role from a PUBLIC grant.

Which roles can use pg_net#

The following table shows how each kind of role can reach the net schema.

RoleCan use pg_netReason
anon, authenticated, service_roleNo, by defaultThese roles can't connect to the database directly, and the Data API doesn't expose net by default.
postgres and any role you create with loginYesThe role can read and change rows in net.http_request_queue and net._http_response. The worker sends each row in the queue.

On some projects, only postgres, anon, authenticated, service_role, and supabase_functions_admin can call net.http_get and net.http_post. For the events that revoke execute from PUBLIC, see When the default grants are applied. A role you create can still add rows to the queue, and the worker sends them. To check a role, run the has_function_privilege query from Check which roles have access.

A row in net.http_request_queue holds the request's URL, headers, and body until the pg_net worker sends it. To check what a queued request exposes, see Database roles can read request headers queued by pg_net.

Limit pg_net access on your project#

Supabase doesn't support changing the grants on pg_net objects for individual projects, so treat the default grants as a platform constraint.

Removing the PUBLIC grants on the net tables breaks pg_net, because the postgres role reaches those tables only through them. Without the grants, a request function called as postgres fails with permission denied for table http_request_queue, which also breaks pg_cron jobs that call pg_net.

To reduce what pg_net exposes:

  • Give the login attribute only to roles for services that you trust to send HTTP requests from your database.
  • Treat any credential you send in request headers as readable by every role that can connect to your database.
  • Keep net out of the exposed schemas in your API settings. If you expose it, anon and authenticated can read net.http_request_queue through the PUBLIC grants, including queued credentials.
  • If your project doesn't use pg_net, drop the extension. Dropping it removes the net schema and all of its grants.

To drop the extension, run:

drop extension pg_net;

When the default grants are applied#

Dropping and re-creating the extension doesn't remove the grants, because create extension pg_net applies all of them again. Two other events grant usage on net to anon, authenticated, and service_role again:

  • A major Postgres version upgrade.
  • Turning on Database Webhooks.

A major Postgres version upgrade also revokes execute on net.http_get and net.http_post from PUBLIC, and grants it to postgres, anon, authenticated, service_role, and supabase_functions_admin. The same happens when pg_net 0.11 or earlier is enabled on a project.