{"record":{"id":"ff9290b45bacf10f","repo":"apache/cassandra","slug":"access-denied-ff9290","errorCode":null,"errorMessage":"Access Denied","messagePattern":"Access Denied","errorType":"exception","errorClass":"java.lang.SecurityException","httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/auth/jmx/AuthorizationProxy.java","lineNumber":200,"sourceCode":"\n                if (args[0] == null)\n                    throw new IllegalArgumentException(\"Null MBeanServer\");\n\n                if (mbs != null)\n                    throw new IllegalArgumentException(\"MBeanServer already initialized\");\n\n                mbs = (MBeanServer) args[0];\n                return null;\n            }\n\n            if (authorize(subject, methodName, args))\n            {\n                Object invoke = invoke(method, args);\n                listener.onInvocation(subject, method, args);\n                return invoke;\n            }\n\n            throw new SecurityException(\"Access Denied\");\n        }\n        catch (Exception e)\n        {\n            listener.onFailure(subject, method, args, e);\n            throw e;\n        }\n    }\n\n    /**\n     * Performs the actual authorization of an identified subject to execute a remote method invocation.\n     * @param subject The principal making the execution request. A null value represents a local invocation\n     *                from the JMX connector itself\n     * @param methodName Name of the method being invoked\n     * @param args Array containing invocation argument. If the first element is an ObjectName instance, for\n     *             authz purposes we consider this an invocation of an MBean method, otherwise it is treated\n     *             as an invocation of a method on the MBeanServer.\n     */\n    @VisibleForTesting","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/auth/jmx/AuthorizationProxy.java#L182-L218","documentation":"This is the terminal authorization failure: authorize(subject, methodName, args) returned false for the authenticated JMX client's operation, so the proxy throws SecurityException(\"Access Denied\") at line 200. It means the calling role does not hold the JMX permission (e.g. READ/WRITE/EXECUTE on the target MBean) required by the configured IAuthorizer, or authorization is required but no matching permission was found.","triggerScenarios":"An authenticated subject invokes any MBeanServerConnection method (getAttribute, setAttribute, invoke, queryNames, etc.) whose required JMX Permission — determined per Permissions/PermissionsMapping and the object name — is not granted to any of the subject's roles via LIST AUTHORIZED JMX / IAuthorizer permissions.","commonSituations":"Monitoring users (e.g. Prometheus JMX exporter) connected with a role lacking read grants on org.apache.cassandra.* MBeans; calling EXECUTE-style MBean methods (like repair or snapshot) with a read-only role; forgetting to GRANT JMX permissions after switching authorizer to CassandraAuthorizer; pattern ObjectName targets where none of the matching MBeans are authorized.","solutions":["Grant the role the needed JMX permission, e.g. GRANT EXECUTE ON MBEAN 'org.apache.cassandra.db:type=StorageService' TO role; (or READ/ WRITE as appropriate).","Verify the authorizer: set authorizer: CassandraAuthorizer and jmx authorization on in cassandra.yaml; permissions may be cached — shorten permissions_validity_in_ms or run a fresh login to pick up new grants.","Inspect the audit log entry emitted by listener.onFailure (JmxInvocationHandler/AuditLogManager) to see exactly which subject/method/target was denied, then grant precisely that permission.","If the operation targets a pattern ObjectName, grant permissions on every matching MBean or narrow the query."],"exampleFix":"// before: role with no grants — monitoring fails with Access Denied\n// after (cqlsh):\nGRANT SELECT ON ALL MBEANS TO monitoring_role;\n// or narrower:\nGRANT EXECUTE ON MBEANS 'org.apache.cassandra.net:type=FailureDetector' TO monitoring_role;","handlingStrategy":"validation","validationCode":"// cqlsh pre-check for the role's grants before using the JMX role in tooling:\n// LIST ALL PERMISSIONS OF monitoring_role;\n// ensure the required permission (READ/WRITE/EXECUTE on the target MBEAN(S)) appears.","typeGuard":null,"tryCatchPattern":"try {\n    return connection.getAttribute(objectName, attribute);\n} catch (SecurityException e) {\n    logger.error(\"JMX access denied for \" + objectName + \"; check GRANT ... ON MBEAN(S) ... TO <role>\", e);\n    throw e; // retrying without a grant will never succeed\n}","preventionTips":["Provision JMX grants (GRANT READ/EXECUTE ON MBEAN(S) ... TO role) as part of role creation for monitoring users.","Keep permissions_validity_in_ms in mind — freshly granted permissions may be cached; wait or lower the TTL when testing.","Check the audit log (listener.onFailure) to identify denied subject/method pairs after config changes.","After switching the authorizer to CassandraAuthorizer, audit all JMX-dependent tooling for missing grants.","Restrict pattern ObjectName queries to MBeans the role is known to be authorized for."],"tags":["jmx","authorization","rbac","security"],"backgroundTag":"insufficient-permissions","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"}