You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Supabase grants some role memberships as supabase_admin, and the postgres role can't revoke them. You see one of the following:
revoke my_role from postgres completes, but the membership stays.
revoke ... granted by supabase_admin fails with permission denied to revoke privileges granted by role "supabase_admin".
drop role my_role fails with permission denied to drop role.
Postgres reports the skipped revoke as a warning in your Postgres logs, not as an error. This page helps you find who granted a membership and work with the roles you create.
In Postgres, a role can revoke only the privileges and memberships that it granted. For more information about grantors and revoking, see the Postgres documentation on REVOKE.
The postgres role isn't a superuser. It can't become supabase_admin or the other Supabase administrator roles, because only a superuser can grant membership in them. As a result, postgres can't act as these roles to change what they granted.
Postgres records the grantor of each role membership. On Postgres 16 or later, when postgres creates a role, Postgres grants postgres an admin membership in the new role. The bootstrap superuser, supabase_admin, is recorded as the grantor. The memberships that Supabase grants to its own roles and to postgres also have supabase_admin as the grantor.
The admin membership in roles you create
Every role you create gets this admin membership, and you can't remove it. The membership has these properties:
It lets postgres drop the role and grant it to other roles. Without it, only a superuser could do that.
It has inherit and set turned off. postgres doesn't receive the role's privileges, and it can run set role to the role only after it grants itself the set option.
Other roles can act as your role only if you grant it to them.
Memberships that Supabase grants
Supabase grants postgres membership in anon, authenticated, service_role, authenticator, pg_read_all_data, pg_monitor, pg_signal_backend, and other roles. The Data API connects as authenticator and switches to anon, authenticated, or service_role for each request, so authenticator is a member of those roles.
revoke admin option for my_role from postgres completes without changing anything, because supabase_admin granted the admin membership. If your migrations contain this statement, remove it.
grant ... granted by supabase_admin fails with permission denied to grant privileges as role "supabase_admin".
Diagnose the problem
List who granted a role's memberships
To list the memberships of a role and who granted each one, replace my_role in the following query.
Run the following SQL using the SQL Editor in the Supabase Dashboard or with psql over a direct connection. To connect with psql, see Direct connection.
selectm.roleid::regrole as role,
m.member::regrole as member,
m.grantor::regrole as grantor,
m.admin_option,
m.inherit_option,
m.set_optionfrom pg_auth_members m
wherem.roleid='my_role'::regrole
orm.member='my_role'::regrole;
Find roles that postgres can't drop or grant
If postgres doesn't have the admin option on a role, it can't drop or grant the role. A grant fails with permission denied to grant role "my_role", and drop role my_role fails with:
ERROR: 42501: permission denied to drop role
DETAIL: Only roles with the CREATEROLE attribute and the ADMIN option on role "my_role" may drop this role.
The following query lists the roles, other than the Supabase roles, that postgres can't drop or grant.
Run the following SQL using the SQL Editor in the Supabase Dashboard or with psql over a direct connection. To connect with psql, see Direct connection.
selectr.rolnamefrom pg_roles as r
wherer.rolname not like'pg\_%'andr.rolname not like'supabase\_%'andr.rolname not like'pgsodium\_%'andr.rolname not like'cli\_login\_%'andr.rolname not in (
'postgres',
'anon',
'authenticated',
'authenticator',
'service_role',
'dashboard_user',
'pgbouncer',
'pgtle_admin'
)
and not pg_has_role('postgres', r.oid, 'member with admin option');
Read the output
In the first query, if grantor is supabase_admin, postgres can't revoke that membership.
The second query lists roles that postgres can't drop or grant. You can still stop clients from connecting as them. See Stop clients from connecting as a role.
Solve the problem
Change an object's owner to a role you create
To change an object's owner to your role, postgres must be able to run set role to it, and your role needs create on the object's schema. Otherwise, alter ... owner to fails with must be able to SET ROLE "my_role" or permission denied for schema.
The following SQL grants both for the change only, then removes them.
Run the following SQL using the SQL Editor in the Supabase Dashboard or with psql over a direct connection. To connect with psql, see Direct connection.
grant create on schema private to my_role;
grant my_role to postgres with set true, inherit false;
alterfunctionprivate.my_function() owner to my_role;
revoke my_role from postgres;
revoke create on schema private from my_role;
The first revoke removes only the membership that postgres granted. The admin membership granted by supabase_admin stays, with set turned off.
Re-create a membership you removed
To re-create a membership, grant it again with the options it had.
Run the following SQL using the SQL Editor in the Supabase Dashboard or with psql over a direct connection. To connect with psql, see Direct connection.
grant my_role to other_role with admin false, inherit false, set true;
Postgres records postgres as the grantor. You can't record supabase_admin as the grantor. The grantor doesn't change what the membership allows. It decides which role can revoke the membership.
Stop clients from connecting as a role
postgres can run alter role on any role you create, including roles it can't drop or grant.
To stop clients from connecting as a role, set it to nologin.
Run the following SQL using the SQL Editor in the Supabase Dashboard or with psql over a direct connection. To connect with psql, see Direct connection.
alter role my_role nologin;
Give services their own roles
To limit what a service or person can do, give them their own role with only the grants they need. Keep the postgres credentials for administration.
Confirm the problem is solved
After you change an owner, check what postgres can do with the role.
Run the following SQL using the SQL Editor in the Supabase Dashboard or with psql over a direct connection. To connect with psql, see Direct connection.
select
pg_has_role('postgres', 'my_role', 'set') as can_set_role,
pg_has_role('postgres', 'my_role', 'usage') as has_privileges;
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Supabase grants some role memberships as
supabase_admin, and thepostgresrole can't revoke them. You see one of the following:revoke my_role from postgrescompletes, but the membership stays.revoke ... granted by supabase_adminfails withpermission denied to revoke privileges granted by role "supabase_admin".drop role my_rolefails withpermission denied to drop role.Postgres reports the skipped revoke as a warning in your Postgres logs, not as an error. This page helps you find who granted a membership and work with the roles you create.
If a role you created needs access to Auth data, see Permission errors when granting custom roles access to the auth schema.
Overview
In Postgres, a role can revoke only the privileges and memberships that it granted. For more information about grantors and revoking, see the Postgres documentation on
REVOKE.The
postgresrole isn't a superuser. It can't becomesupabase_adminor the other Supabase administrator roles, because only a superuser can grant membership in them. As a result,postgrescan't act as these roles to change what they granted.Postgres records the grantor of each role membership. On Postgres 16 or later, when
postgrescreates a role, Postgres grantspostgresanadminmembership in the new role. The bootstrap superuser,supabase_admin, is recorded as the grantor. The memberships that Supabase grants to its own roles and topostgresalso havesupabase_adminas the grantor.The admin membership in roles you create
Every role you create gets this
adminmembership, and you can't remove it. The membership has these properties:postgresdrop the role and grant it to other roles. Without it, only a superuser could do that.inheritandsetturned off.postgresdoesn't receive the role's privileges, and it can runset roleto the role only after it grants itself thesetoption.Memberships that Supabase grants
Supabase grants
postgresmembership inanon,authenticated,service_role,authenticator,pg_read_all_data,pg_monitor,pg_signal_backend, and other roles. The Data API connects asauthenticatorand switches toanon,authenticated, orservice_rolefor each request, soauthenticatoris a member of those roles.When you run the Supabase CLI without a database password, Supabase creates a temporary
cli_login_postgresrole that is a member ofpostgres. To remove it, see 'Permission denied' when deleting the 'cli_login_postgres' role.Statements that don't work
revoke admin option for my_role from postgrescompletes without changing anything, becausesupabase_admingranted theadminmembership. If your migrations contain this statement, remove it.grant ... granted by supabase_adminfails withpermission denied to grant privileges as role "supabase_admin".Diagnose the problem
List who granted a role's memberships
To list the memberships of a role and who granted each one, replace
my_rolein the following query.Run the following SQL using the SQL Editor in the Supabase Dashboard or with
psqlover a direct connection. To connect withpsql, see Direct connection.Find roles that postgres can't drop or grant
If
postgresdoesn't have theadminoption on a role, it can't drop or grant the role. A grant fails withpermission denied to grant role "my_role", anddrop role my_rolefails with:The following query lists the roles, other than the Supabase roles, that
postgrescan't drop or grant.Run the following SQL using the SQL Editor in the Supabase Dashboard or with
psqlover a direct connection. To connect withpsql, see Direct connection.Read the output
grantorissupabase_admin,postgrescan't revoke that membership.postgrescan't drop or grant. You can still stop clients from connecting as them. See Stop clients from connecting as a role.Solve the problem
Change an object's owner to a role you create
To change an object's owner to your role,
postgresmust be able to runset roleto it, and your role needscreateon the object's schema. Otherwise,alter ... owner tofails withmust be able to SET ROLE "my_role"orpermission denied for schema.The following SQL grants both for the change only, then removes them.
Run the following SQL using the SQL Editor in the Supabase Dashboard or with
psqlover a direct connection. To connect withpsql, see Direct connection.The first
revokeremoves only the membership thatpostgresgranted. Theadminmembership granted bysupabase_adminstays, withsetturned off.Re-create a membership you removed
To re-create a membership, grant it again with the options it had.
Run the following SQL using the SQL Editor in the Supabase Dashboard or with
psqlover a direct connection. To connect withpsql, see Direct connection.Postgres records
postgresas the grantor. You can't recordsupabase_adminas the grantor. The grantor doesn't change what the membership allows. It decides which role can revoke the membership.Stop clients from connecting as a role
postgrescan runalter roleon any role you create, including roles it can't drop or grant.To stop clients from connecting as a role, set it to
nologin.Run the following SQL using the SQL Editor in the Supabase Dashboard or with
psqlover a direct connection. To connect withpsql, see Direct connection.Give services their own roles
To limit what a service or person can do, give them their own role with only the grants they need. Keep the
postgrescredentials for administration.Confirm the problem is solved
After you change an owner, check what
postgrescan do with the role.Run the following SQL using the SQL Editor in the Supabase Dashboard or with
psqlover a direct connection. To connect withpsql, see Direct connection.Both values are
falseafter therevoke.After you re-create a membership, run the query in List who granted a role's memberships. The
grantorof the new membership ispostgres.Related topics
All reactions