apache/cassandra · error · UnauthorizedException

You are not authorized to view roles granted to %s

Error message

You are not authorized to view roles granted to %s 

What it means

When a user without root-level DESCRIBE ('all roles') permission runs LIST ROLES OF <grantee>, Cassandra only shows the grantee's roles if the grantee is in the current user's (recursive) grant chain; otherwise UnauthorizedException is thrown. This prevents privilege escalation via enumerating other roles' memberships.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/ListRolesStatement.java:115

                                                       .authorize(state.getUser(), RoleResource.root())
                                                       .contains(Permission.DESCRIBE);
        if (hasRootLevelSelect)
        {
            if (grantee == null)
                return resultMessage(DatabaseDescriptor.getRoleManager().getAllRoles());
            if (!DatabaseDescriptor.getRoleManager().isExistingRole(grantee))
                throw new InvalidRequestException(String.format("%s doesn't exist", grantee));
            return resultMessage(DatabaseDescriptor.getRoleManager().getRoles(grantee, recursive));
        }
        else
        {
            RoleResource currentUser = RoleResource.role(state.getUser().getName());
            if (grantee == null)
                return resultMessage(DatabaseDescriptor.getRoleManager().getRoles(currentUser, recursive));
            if (DatabaseDescriptor.getRoleManager().getRoles(currentUser, true).contains(grantee))
                return resultMessage(DatabaseDescriptor.getRoleManager().getRoles(grantee, recursive));
            else
                throw new UnauthorizedException(String.format("You are not authorized to view roles granted to %s ", grantee.getRoleName()));
        }
    }

    private ResultMessage resultMessage(Set<RoleResource> roles)
    {
        if (roles.isEmpty())
            return new ResultMessage.Void();

        List<RoleResource> sorted = Lists.newArrayList(roles);
        Collections.sort(sorted);
        return formatResults(sorted);
    }

    // overridden in ListUsersStatement to include legacy metadata
    protected ResultMessage formatResults(List<RoleResource> sortedRoles)
    {
        ResultSet.ResultMetadata resultMetadata = new ResultSet.ResultMetadata(metadata);
        ResultSet result = new ResultSet(resultMetadata);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Have a superuser grant the caller DESCRIBE on all roles: GRANT DESCRIBE ON ALL ROLES TO <user>
  2. Ask a superuser to run the LIST ROLES OF query instead
  3. Check roles within your own grant chain: LIST ROLES (without OF)

Example fix

// before
LIST ROLES OF finance_auditor; // as non-privileged user -> UnauthorizedException
// after
GRANT DESCRIBE ON ALL ROLES TO ops_user; // run by superuser
LIST ROLES OF finance_auditor;
Defensive patterns

Strategy: validation

Validate before calling

boolean hasDescribe = DatabaseDescriptor.getAuthorizer()
    .authorize(user, RoleResource.root()).contains(Permission.DESCRIBE);
boolean inMyChain = DatabaseDescriptor.getRoleManager().getRoles(myRole, true).contains(grantee);
if (!hasDescribe && !inMyChain) throw new IllegalStateException("not authorized to view roles granted to " + grantee);

Try / catch

try { session.execute("LIST ROLES OF " + grantee); } catch (UnauthorizedException e) { log.warn("need DESCRIBE ON ALL ROLES (or own the role chain) to view {}", grantee); }

Prevention

When it happens

Trigger: Non-privileged user executes LIST ROLES OF <role> where <role> exists but is not granted (directly or transitively) to the executing user, i.e. not contained in getRoles(currentUser, true).

Common situations: Helpdesk/ops staff assuming they can audit arbitrary roles; multi-team clusters where roles are siloed per team; confusion about the DESCRIBE-on-all-roles requirement.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/c184e9ba66d3660d. Report an issue: GitHub.