apache/cassandra · error · AccessControlException

Access denied

Error message

Access denied

What it means

ThreadAwareSecurityManager.checkPermission throws AccessControlException("Access denied") when code running in a secured UDF thread tries to set the JVM SecurityManager. This is only allowed when user-defined-function threads are enabled AND extra insecure UDF permissions are explicitly allowed. It is a deliberate sandbox guard preventing UDF code from replacing or disabling Cassandra's security manager.

Source

Thrown at src/java/org/apache/cassandra/security/ThreadAwareSecurityManager.java:211

        if (isSecuredThread())
            throw new AccessControlException("access denied: " + MODIFY_THREAD_PERMISSION, MODIFY_THREAD_PERMISSION);
        super.checkAccess(t);
    }

    public void checkAccess(ThreadGroup g)
    {
        // need to override since the default implementation only checks the permission if the current thread's
        // in the root-thread-group

        if (isSecuredThread())
            throw new AccessControlException("access denied: " + MODIFY_THREADGROUP_PERMISSION, MODIFY_THREADGROUP_PERMISSION);
        super.checkAccess(g);
    }

    public void checkPermission(Permission perm)
    {
        if (!DatabaseDescriptor.enableUserDefinedFunctionsThreads() && !DatabaseDescriptor.allowExtraInsecureUDFs() && SET_SECURITY_MANAGER_PERMISSION.equals(perm))
            throw new AccessControlException("Access denied");

        if (!isSecuredThread())
            return;

        // required by JavaDriver 2.2.0-rc3 and 3.0.0-a2 or newer
        // code in com.datastax.driver.core.CodecUtils uses Guava stuff, which in turns requires this permission
        // TODO: Evaluate removing this once the driver is removed as a dependency (see CASSANDRA-20326).
        if (CHECK_MEMBER_ACCESS_PERMISSION.equals(perm))
            return;

        // Nashorn / Java 11
        if (NASHORN_GLOBAL_PERMISSION.equals(perm))
            return;
        if (SUPPRESS_ACCESS_CHECKS_PERMISSION.equals(perm))
            return;
        if (DYNALINK_LOOKUP_PERMISSION.equals(perm))
            return;
        if (GET_CLASSLOADER_PERMISSION.equals(perm))

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Do not call System.setSecurityManager() from UDF code; it is forbidden by the sandbox.
  2. If you genuinely need it, set enable_user_defined_functions_threads: true and allow_extra_insecure_udfs: true in cassandra.yaml, understanding the security risk.
  3. Move the privileged operation out of the UDF and into application code talking to Cassandra via a client.
  4. Run the cluster without user-defined functions if untrusted code must never execute.

Example fix

// before (inside UDF)
System.setSecurityManager(null); // throws AccessControlException
// after
// remove the call; perform privileged setup outside UDFs, or enable
// enable_user_defined_functions_threads + allow_extra_insecure_udfs in cassandra.yaml
Defensive patterns

Strategy: try-catch

Validate before calling

boolean canSetSecurityManager = DatabaseDescriptor.enableUserDefinedFunctionsThreads() && DatabaseDescriptor.allowExtraInsecureUDFs();
if (!canSetSecurityManager) throw new IllegalStateException("setSecurityManager not permitted in UDF threads");

Try / catch

try { System.setSecurityManager(sm); } catch (AccessControlException e) { log.warn("SecurityManager change blocked in UDF sandbox", e); }

Prevention

When it happens

Trigger: A user-defined function (or driver/Guava code invoked from a UDF thread) calls System.setSecurityManager() while enableUserDefinedFunctionsThreads is false (or allowExtraInsecureUDFs is false), so the SET_SECURITY_MANAGER_PERMISSION check in checkPermission (src/java/org/apache/cassandra/security/ThreadAwareSecurityManager.java:211) rejects it.

Common situations: UDFs that attempt privileged operations like installing a security manager; enabling UDFs without udf_enabled / allow_extra_insecure_udfs flags in cassandra.yaml; upgrading clusters where UDF sandboxing became stricter.

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