Class DefaultQueryExpressionValidator

java.lang.Object
org.camunda.bpm.engine.impl.query.DefaultQueryExpressionValidator
All Implemented Interfaces:
QueryExpressionValidator

public class DefaultQueryExpressionValidator extends Object implements QueryExpressionValidator
Default QueryExpressionValidator that protects query expressions from referencing arbitrary EL functions or beans.

How validation works

The expression string is parsed into a JUEL AST using Builder.build(String) with Builder.Feature.METHOD_INVOCATIONS enabled – the same feature set used by the engine’s own evaluator. The resulting tree is then walked recursively:

  • AstFunction – EL function call without a receiver (e.g. now(), prefix:func()). The local name is checked against the function allow-list.
  • AstMethod – instance method call with a receiver, e.g. dateTime().plusDays(1). Dot-notation calls are validated against the function allow-list; bracket-notation calls (x['method'](), x[var]()) are rejected unconditionally because the method name may not be statically determinable.
  • AstIdentifier – standalone bare name (${myBean}). Checked against the bean allow-list.
  • AstDot – dot-notation property access without a following invocation (e.g. ${obj.field}). The property name is checked against the property allow-list. Dot nodes that appear as method-name carriers inside an AstMethod are handled there and are not re-visited here.
  • AstBracket – bracket property access (${map['key']}, ${list[0]}) is recursed into without restriction when it is not followed by an invocation (); the bracket value and index children are visited recursively.

An expression that cannot be parsed is rejected with BadUserRequestException.

Default allow-list (always permitted)

  • Functions: now, dateTime, currentUser, currentUserGroups
  • Joda-Time DateTime arithmetic methods: plusDays, minusDays, withHourOfDay, etc. (full list in DEFAULT_ALLOWED_FUNCTIONS)
  • Beans: none – all bean access is blocked unless explicitly configured via setAllowedBeans(String).
  • Properties: none – all dot-notation property access is blocked unless explicitly configured via setAllowedProperties(String).

Extending the allow-list

Use the process engine configuration properties allowedExpressionFunctionsInQueries, allowedExpressionBeansInQueries, and allowedExpressionPropertiesInQueries (comma-separated lists) to extend the defaults with additional names that are safe in your environment.
See Also:
  • Field Details

  • Constructor Details

    • DefaultQueryExpressionValidator

      public DefaultQueryExpressionValidator()
  • Method Details

    • formatQueryExpressionParseErrorMessage

      public static String formatQueryExpressionParseErrorMessage(String expressionText, String parserMessage)
    • formatBracketMethodInvocationNotAllowedMessage

      public static String formatBracketMethodInvocationNotAllowedMessage(String expressionText)
    • formatPropertyNotAllowedMessage

      public static String formatPropertyNotAllowedMessage(String propertyName, String expressionText)
    • formatFunctionNotAllowedMessage

      public static String formatFunctionNotAllowedMessage(String functionName, String expressionText)
    • formatBeanNotAllowedMessage

      public static String formatBeanNotAllowedMessage(String beanName, String expressionText)
    • setAllowedFunctions

      public void setAllowedFunctions(String functions)
      Populates the additional (admin-configured) function allow-list from a comma-separated string. Does not affect the built-in defaults.
      Parameters:
      functions - comma-separated function names, e.g. "myFunc,otherFunc"
    • setAllowedBeans

      public void setAllowedBeans(String beans)
      Populates the bean allow-list from a comma-separated string.
      Parameters:
      beans - comma-separated bean names, e.g. "myBean,anotherBean"
    • setAllowedProperties

      public void setAllowedProperties(String properties)
      Populates the property allow-list from a comma-separated string.
      Parameters:
      properties - comma-separated property names, e.g. "assignee,dueDate"
    • validateExpression

      public void validateExpression(String expressionText)
      Validates expressionText by parsing it into a JUEL AST and walking every node. No evaluation takes place.

      If the expression cannot be parsed it is rejected immediately with a BadUserRequestException: an expression the EL parser itself cannot understand cannot be on any allow-list.

      Specified by:
      validateExpression in interface QueryExpressionValidator
      Parameters:
      expressionText - the full expression string as supplied by the caller (e.g. "${currentUser()}")
      Throws:
      BadUserRequestException - when a disallowed function, method, property, or bean is found, or when the expression cannot be parsed
    • visitNode

      protected void visitNode(Node node, String fullExpression)
      Recursively walks the JUEL AST and validates every function call, method invocation, and identifier against the configured allow-lists.
      • AstFunction – EL function call without a receiver (now(), prefix:func()). Strips any namespace prefix and checks the local name against the function allow-list.
      • AstMethod – instance method call with a receiver.
        • Dot-notation (receiver.method()) – extracts the method name from the AstDot child and validates it against the function allow-list.
        • Bracket-notation (receiver['method']() or receiver[var]()) – the method name may not be statically determinable, so all bracket invocations are rejected unconditionally.
      • AstIdentifier – standalone bare name (${myBean}). Checked against the bean allow-list.
      • AstDot – dot-notation property access without a following invocation, e.g. ${obj.field}. The property name is checked against the property allow-list. (When an AstDot is used as the method-name carrier inside an AstMethod it is handled there, not here.)
      • All other node types (literals, operators, EL keywords, etc.) are passed through without validation; their children are visited recursively.
      Parameters:
      node - the AST node to inspect (plus its descendants)
      fullExpression - the original expression text, used only for constructing error messages
    • validateProperty

      protected void validateProperty(String propertyName, String expressionText)
      Checks that the given property name (dot-notation, non-invocation access) is on the explicit property allow-list.

      No built-in defaults exist for properties: every property name must be explicitly configured via allowedExpressionPropertiesInQueries.

      Throws:
      BadUserRequestException - when the property is not allowed
    • validateFunction

      protected void validateFunction(String functionName, String expressionText)
      Checks that the given function name is on the allow-list.
      Throws:
      BadUserRequestException - when the function is not allowed
    • validateBean

      protected void validateBean(String beanName, String expressionText)
      Checks that the given bean name is on the allow-list.
      Throws:
      BadUserRequestException - when the bean is not allowed
    • extractElements

      protected void extractElements(String commaSeparated, Set<String> target)