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
- Have a superuser grant the caller DESCRIBE on all roles: GRANT DESCRIBE ON ALL ROLES TO <user>
- Ask a superuser to run the LIST ROLES OF query instead
- 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
- Request GRANT DESCRIBE ON ALL ROLES for auditing roles
- Audit only roles within your own grant chain when unprivileged
- Centralize role audits under a superuser service account
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
- Only superusers can drop a role with superuser status
- You are not authorized to view superuser details
- You aren't allowed to alter %s
- %s doesn't exist
- Cannot DROP primary role for current login
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/c184e9ba66d3660d.
Report an issue: GitHub.