{"record":{"id":"c184e9ba66d3660d","repo":"apache/cassandra","slug":"you-are-not-authorized-to-view-roles-granted-to-s","errorCode":null,"errorMessage":"You are not authorized to view roles granted to %s ","messagePattern":"You are not authorized to view roles granted to (.+?) ","errorType":"validation","errorClass":"UnauthorizedException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/ListRolesStatement.java","lineNumber":115,"sourceCode":"                                                       .authorize(state.getUser(), RoleResource.root())\n                                                       .contains(Permission.DESCRIBE);\n        if (hasRootLevelSelect)\n        {\n            if (grantee == null)\n                return resultMessage(DatabaseDescriptor.getRoleManager().getAllRoles());\n            if (!DatabaseDescriptor.getRoleManager().isExistingRole(grantee))\n                throw new InvalidRequestException(String.format(\"%s doesn't exist\", grantee));\n            return resultMessage(DatabaseDescriptor.getRoleManager().getRoles(grantee, recursive));\n        }\n        else\n        {\n            RoleResource currentUser = RoleResource.role(state.getUser().getName());\n            if (grantee == null)\n                return resultMessage(DatabaseDescriptor.getRoleManager().getRoles(currentUser, recursive));\n            if (DatabaseDescriptor.getRoleManager().getRoles(currentUser, true).contains(grantee))\n                return resultMessage(DatabaseDescriptor.getRoleManager().getRoles(grantee, recursive));\n            else\n                throw new UnauthorizedException(String.format(\"You are not authorized to view roles granted to %s \", grantee.getRoleName()));\n        }\n    }\n\n    private ResultMessage resultMessage(Set<RoleResource> roles)\n    {\n        if (roles.isEmpty())\n            return new ResultMessage.Void();\n\n        List<RoleResource> sorted = Lists.newArrayList(roles);\n        Collections.sort(sorted);\n        return formatResults(sorted);\n    }\n\n    // overridden in ListUsersStatement to include legacy metadata\n    protected ResultMessage formatResults(List<RoleResource> sortedRoles)\n    {\n        ResultSet.ResultMetadata resultMetadata = new ResultSet.ResultMetadata(metadata);\n        ResultSet result = new ResultSet(resultMetadata);","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/ListRolesStatement.java#L97-L133","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)"],"exampleFix":"// before\nLIST ROLES OF finance_auditor; // as non-privileged user -> UnauthorizedException\n// after\nGRANT DESCRIBE ON ALL ROLES TO ops_user; // run by superuser\nLIST ROLES OF finance_auditor;","handlingStrategy":"validation","validationCode":"boolean hasDescribe = DatabaseDescriptor.getAuthorizer()\n    .authorize(user, RoleResource.root()).contains(Permission.DESCRIBE);\nboolean inMyChain = DatabaseDescriptor.getRoleManager().getRoles(myRole, true).contains(grantee);\nif (!hasDescribe && !inMyChain) throw new IllegalStateException(\"not authorized to view roles granted to \" + grantee);","typeGuard":null,"tryCatchPattern":"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); }","preventionTips":["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"],"tags":["cassandra","cql","authorization","roles","privilege-escalation"],"backgroundTag":"permission-denied","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}