{"record":{"id":"b466f657b7181748","repo":"apache/cassandra","slug":"granting-permissions-on-system-keyspaces-is-strict","errorCode":null,"errorMessage":"Granting permissions on system keyspaces is strictly limited, this operation is not permitted","messagePattern":"Granting permissions on system keyspaces is strictly limited, this operation is not permitted","errorType":"validation","errorClass":"UnauthorizedException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/GrantPermissionsStatement.java","lineNumber":58,"sourceCode":"public class GrantPermissionsStatement extends PermissionsManagementStatement\n{\n    public GrantPermissionsStatement(Set<Permission> permissions, IResource resource, RoleName grantee)\n    {\n        super(permissions, resource, grantee);\n    }\n\n    public void validate(ClientState state) throws RequestValidationException\n    {\n        super.validate(state);\n        if (resource instanceof DataResource)\n        {\n            DataResource data = (DataResource) resource;\n            // Only a subset of permissions can be granted on non-virtual system keyspaces\n            if (!data.isRootLevel()\n                && SchemaConstants.isNonVirtualSystemKeyspace(data.getKeyspace())\n                && !Collections.disjoint(permissions, Permission.INVALID_FOR_SYSTEM_KEYSPACES))\n            {\n                throw new UnauthorizedException(\"Granting permissions on system keyspaces is strictly limited, \" +\n                                                \"this operation is not permitted\");\n            }\n        }\n    }\n\n    public ResultMessage execute(ClientState state) throws RequestValidationException, RequestExecutionException\n    {\n        IAuthorizer authorizer = DatabaseDescriptor.getAuthorizer();\n        Set<Permission> granted = authorizer.grant(state.getUser(), permissions, resource, grantee);\n\n        // We want to warn the client if all the specified permissions have not been granted and the client did\n        // not specify ALL in the query.\n        if (!granted.equals(permissions) && !permissions.equals(Permission.ALL))\n        {\n            String permissionsStr = permissions.stream()\n                                               .filter(permission -> !granted.contains(permission))\n                                               .sorted(Permission::compareTo) // guarantee the order for testing\n                                               .map(Permission::name)","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/GrantPermissionsStatement.java#L40-L76","documentation":"Cassandra forbids granting most permissions on (non-virtual) system keyspaces; only a tightly limited subset is allowed. If the granted permission set overlaps Permission.INVALID_FOR_SYSTEM_KEYSPACES on such a resource, UnauthorizedException is thrown during validate().","triggerScenarios":"GRANT <permission> ON KEYSPACE <system-ish-keyspace> where the keyspace is in SchemaConstants non-virtual system keyspace list (e.g. system, system_schema, system_auth) and the permission is one of the invalid ones (e.g. MODIFY, DROP, ALTER).","commonSituations":"Attempts to let application users write into system_auth or system_schema; misconfigured provisioning tools that grant blanket permissions including system keyspaces; confusion between virtual keyspaces (allowed differently) and non-virtual ones.","solutions":["Grant on a user-defined keyspace instead of the system keyspace","Restrict the grant to permissions valid for system keyspaces (those not in INVALID_FOR_SYSTEM_KEYSPACES, e.g. SELECT where permitted)","Use role-based access on application data rather than opening system keyspaces"],"exampleFix":"// before\nGRANT MODIFY ON KEYSPACE system_auth TO app_role; // UnauthorizedException\n// after\nGRANT MODIFY ON KEYSPACE my_app TO app_role;","handlingStrategy":"validation","validationCode":"Set<Permission> invalid = Permission.INVALID_FOR_SYSTEM_KEYSPACES;\nboolean isSystemKeyspace = SchemaConstants.isNonVirtualSystemKeyspace(ksName);\nif (isSystemKeyspace && !Collections.disjoint(requested, invalid)) throw new IllegalArgumentException(\"grant not permitted on system keyspace \" + ksName);","typeGuard":null,"tryCatchPattern":"try { session.execute(grant); } catch (UnauthorizedException e) { log.error(\"grant on system keyspace rejected: {}\", e.getMessage()); }","preventionTips":["Never target system/system_schema/system_auth keyspaces in GRANT statements","Whitelist application keyspaces in provisioning tooling","Read SchemaConstants.isNonVirtualSystemKeyspace to know the protected list"],"tags":["cassandra","cql","authorization","permissions","system-keyspaces"],"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"}