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
- Do not call System.setSecurityManager() from UDF code; it is forbidden by the sandbox.
- 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.
- Move the privileged operation out of the UDF and into application code talking to Cassandra via a client.
- 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
- Never call System.setSecurityManager from UDF code
- Keep UDF logic to pure computation over column values
- Only enable allow_extra_insecure_udfs on trusted, non-production clusters
- Review UDF source for privileged API usage before deploying
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- access denied: + MODIFY_THREAD_PERMISSION
- access denied: + MODIFY_THREADGROUP_PERMISSION
- access denied: + perm
- To be able to set enable_user_defined_functions_threads: fal
- Java UDF validation failed:
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/f8cd3a85409d836f.
Report an issue: GitHub.