Activiti/Activiti · error · IllegalArgumentException

Illegal use of Reflection in a JUEL Expression

Error message

Illegal use of Reflection in a JUEL Expression

What it means

ELResolverReflectionBlockerDecorator wraps the JUEL ELResolver and hard-blocks any method invocation whose base object is an instance of java.lang.reflect (package java.lang.reflect), throwing IllegalArgumentException. This is a security guard: JUEL expressions in BPMN/process definitions must not be able to call arbitrary reflection APIs to bypass access control. The throw is deliberate and cannot be disabled safely.

Solutions

  1. Remove the reflective call from the expression and call a dedicated, allow-listed service bean method instead
  2. Expose a task/service delegate or Spring bean that encapsulates the logic and reference it directly in the expression
  3. If reflection is genuinely needed, perform it server-side in Java code, never inside a JUEL expression
  4. Do not remove the blocker decorator — it protects against expression injection

Example fix

// before (BPMN expression)
${execution.setVariable('x', T(java.lang.reflect.Array).newInstance(...))}
// after
${myHelperBean.computeArray(execution)}
Defensive patterns

Strategy: validation

Validate before calling

boolean expressionIsSafe(String expr) {
  return expr != null && !expr.matches("(?s).*java\\.reflect\\..*") && !expr.contains("forName") && !expr.contains("getMethod") && !expr.contains("invoke(");
}

Try / catch

try {
    Object result = valueExpression.getValue(elContext);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Reflection")) { auditLog.security("reflection blocked in EL"); }
    throw e;
}

Prevention

When it happens

Trigger: A JUEL expression like ${Class.forName(...).getMethod(...).invoke(...)} or any expression whose evaluated base object's class package equals java.lang.reflect, reaching ELResolver.invoke.

Common situations: Malicious or copied expressions embedded in BPMN XML process definitions; users pasting Java-style reflective snippets into expression fields; pentest payloads like ${''.getClass().forName('java.lang.Runtime')} traversing reflective objects.

Related errors


AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/0467037fb1d22bd1. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core-common/activiti-expression-language/src/main/java/org/activiti/core/el/ELResolverReflectionBlockerDecorator.java:48

public class ELResolverReflectionBlockerDecorator extends ELResolverDecorator {

    private static final String JAVA_REFLECTION_PACKAGE = "java.lang.reflect";
    private static final Predicate<Method> IS_FINAL = method -> Modifier.isFinal(method.getModifiers());
    private static final Predicate<Method> IS_NATIVE = method -> Modifier.isNative(method.getModifiers());
    private static final Set<String> NATIVE_METHODS = Arrays.stream(Object.class.getMethods())
        .filter(IS_FINAL.or(IS_NATIVE))
        .map(Method::getName)
        .collect(Collectors.toSet());

    public ELResolverReflectionBlockerDecorator(ELResolver resolver) {
        super(resolver);
    }

    @Override
    public Object invoke(ELContext context, Object base, Object method, Class<?>[] paramTypes, Object[] params) {
        final String basePackageName = base.getClass().getPackageName();
        if (JAVA_REFLECTION_PACKAGE.equals(basePackageName)) {
            throw new IllegalArgumentException("Illegal use of Reflection in a JUEL Expression");
        }

        if (NATIVE_METHODS.contains(method)) {
            throw new IllegalArgumentException("Illegal use of Native Method in a JUEL Expression");
        }
        return super.invoke(context, base, method, paramTypes, params);
    }
}

View on GitHub (pinned to 56435b1a97)