apache/cassandra · error · AccessControlException

access denied: + MODIFY_THREAD_PERMISSION

Error message

access denied: + MODIFY_THREAD_PERMISSION

What it means

ThreadAwareSecurityManager overrides checkAccess(Thread) so that threads running secured UDF code are denied thread-manipulation rights even outside the root thread group (where the default SecurityManager would not check). If the current thread is a secured UDF thread, it throws AccessControlException formodifyThreadPermission instead of delegating to super.

Source

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

            return false;
        Boolean threadInitialized = initializedThread.get();
        if (threadInitialized == null)
        {
            initializedThread.set(false);
            ((SecurityThreadGroup) tg).initializeThread();
            initializedThread.set(true);
            threadInitialized = true;
        }
        return threadInitialized;
    }

    public void checkAccess(Thread t)
    {
        // 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_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");

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Remove thread-manipulation logic (stop/suspend/interrupt of other threads) from the UDF; UDFs must be pure computation.
  2. Rewrite the UDF to coordinate via returned data or application-level mechanisms instead of touching threads.
  3. If legitimate, run the code outside UDF context (a regular thread is not flagged as secured).
  4. As a last resort for trusted environments, adjust security settings (enable_user_defined_functions_threads / allow_extra_insecure_udFs) — understand this weakens the sandbox.

Example fix

// before (inside a UDF)
someOtherThread.stop();

// after
return computeResultDirectly(); // no thread manipulation in UDFs
Defensive patterns

Strategy: try-catch

Try / catch

try {
    thread.checkAccess();
} catch (AccessControlException e) {
    logger.warn("Thread access denied in sandboxed UDF context: {}", e.getMessage());
    throw new UnsupportedOperationException("Thread manipulation is not permitted inside UDFs");
}

Prevention

When it happens

Trigger: Code executing inside a Cassandra UDF (sandboxed secured thread) calls Thread.stop(), Thread.suspend(), Thread.resume(), Thread.interrupt() on another thread, or otherwise triggers Thread.checkAccess() while the security manager is active with UDF protection enabled.

Common situations: User-defined functions that try to manipulate or stop other threads; UDFs spawning/interfering with thread groups; migration of UDF code from environments without a security manager to Cassandra's sandboxed UDF execution.

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