apache/cassandra · error · UnauthorizedException

Granting permissions on system keyspaces is strictly limited

Error message

Granting permissions on system keyspaces is strictly limited, this operation is not permitted

What it means

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().

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/GrantPermissionsStatement.java:58

public class GrantPermissionsStatement extends PermissionsManagementStatement
{
    public GrantPermissionsStatement(Set<Permission> permissions, IResource resource, RoleName grantee)
    {
        super(permissions, resource, grantee);
    }

    public void validate(ClientState state) throws RequestValidationException
    {
        super.validate(state);
        if (resource instanceof DataResource)
        {
            DataResource data = (DataResource) resource;
            // Only a subset of permissions can be granted on non-virtual system keyspaces
            if (!data.isRootLevel()
                && SchemaConstants.isNonVirtualSystemKeyspace(data.getKeyspace())
                && !Collections.disjoint(permissions, Permission.INVALID_FOR_SYSTEM_KEYSPACES))
            {
                throw new UnauthorizedException("Granting permissions on system keyspaces is strictly limited, " +
                                                "this operation is not permitted");
            }
        }
    }

    public ResultMessage execute(ClientState state) throws RequestValidationException, RequestExecutionException
    {
        IAuthorizer authorizer = DatabaseDescriptor.getAuthorizer();
        Set<Permission> granted = authorizer.grant(state.getUser(), permissions, resource, grantee);

        // We want to warn the client if all the specified permissions have not been granted and the client did
        // not specify ALL in the query.
        if (!granted.equals(permissions) && !permissions.equals(Permission.ALL))
        {
            String permissionsStr = permissions.stream()
                                               .filter(permission -> !granted.contains(permission))
                                               .sorted(Permission::compareTo) // guarantee the order for testing
                                               .map(Permission::name)

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Grant on a user-defined keyspace instead of the system keyspace
  2. Restrict the grant to permissions valid for system keyspaces (those not in INVALID_FOR_SYSTEM_KEYSPACES, e.g. SELECT where permitted)
  3. Use role-based access on application data rather than opening system keyspaces

Example fix

// before
GRANT MODIFY ON KEYSPACE system_auth TO app_role; // UnauthorizedException
// after
GRANT MODIFY ON KEYSPACE my_app TO app_role;
Defensive patterns

Strategy: validation

Validate before calling

Set<Permission> invalid = Permission.INVALID_FOR_SYSTEM_KEYSPACES;
boolean isSystemKeyspace = SchemaConstants.isNonVirtualSystemKeyspace(ksName);
if (isSystemKeyspace && !Collections.disjoint(requested, invalid)) throw new IllegalArgumentException("grant not permitted on system keyspace " + ksName);

Try / catch

try { session.execute(grant); } catch (UnauthorizedException e) { log.error("grant on system keyspace rejected: {}", e.getMessage()); }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

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/b466f657b7181748. Report an issue: GitHub.