Script Guard

Script Guard is an EximeeBPMS feature that inspects scripts before execution and blocks — or audits — patterns that could lead to remote code execution, data exfiltration, or other security incidents. It works at the engine level, independently of the scripting language in use.

Script Guard applies to all scripts executed by the process engine: Script Tasks, Execution Listeners, Task Listeners, Condition Expressions, and Input/Output Mappings, as well as scripts submitted dynamically via the REST API or Java API.

Enforcement Modes

Script Guard operates in three modes:

ModeBehavior
ENFORCEScripts containing forbidden patterns are rejected. A ScriptSecurityException is thrown before the script executes.
AUDITViolations are recorded but execution continues. Use this mode to inspect existing processes before enabling enforcement.
DISABLEDNo checks are performed. Script Guard is inactive.

The mode can be changed at runtime via the REST API without restarting the engine. All engine nodes pick up the new configuration within 30 seconds.

Blocked Patterns

The built-in policy checks the script source (case-insensitively) against the following patterns:

Rule codeBlocked constructRisk
SCRIPT_SECURITY_LOADload(External script loading
SCRIPT_SECURITY_CLASS_FOR_NAMEClass.forName(Dynamic class loading
SCRIPT_SECURITY_CLASS_LOADERgetClassLoader(Class loader access
SCRIPT_SECURITY_REFLECTIONjava.lang.reflect.Reflection API
SCRIPT_SECURITY_REFLECTION_METHODgetDeclaredMethod(Method reflection
SCRIPT_SECURITY_REFLECTION_FIELDgetDeclaredField(Field reflection
SCRIPT_SECURITY_PROCESS_BUILDERProcessBuilderOS process execution
SCRIPT_SECURITY_RUNTIMEjava.lang.RuntimeJVM runtime access
SCRIPT_SECURITY_RUNTIME_EXECRuntime.getRuntime(OS command execution
SCRIPT_SECURITY_JAVA_LANG_SYSTEMjava.lang.SystemSystem class access
SCRIPT_SECURITY_SYSTEM_EXITSystem.exit(JVM shutdown
SCRIPT_SECURITY_SYSTEM_GETENVSystem.getenv(Environment variable access
SCRIPT_SECURITY_SYSTEM_GET_PROPERTYSystem.getProperty(System property access
SCRIPT_SECURITY_JAVA_IOjava.io.*File system access
SCRIPT_SECURITY_JAVA_NIO_FILEjava.nio.file.*NIO file system access
SCRIPT_SECURITY_JAVA_NIO_FILE_CHANNELNIO file channelsLow-level file I/O
SCRIPT_SECURITY_JAVA_NIO_NETWORK_CHANNELNIO network channelsNetwork socket access
SCRIPT_SECURITY_JAVA_NETjava.net.*Network access
SCRIPT_SECURITY_URL_CONNECTIONURLConnectionHTTP/URL connections
SCRIPT_SECURITY_HTTP_CLIENTHttpClientHTTP client
SCRIPT_SECURITY_SOCKETnew Socket(Raw socket creation
SCRIPT_SECURITY_SERVER_SOCKETServerSocketServer socket binding
SCRIPT_SECURITY_NEW_JAVAnew java.*Generic Java object instantiation
SCRIPT_SECURITY_GROOVY_SHELLGroovyShellDynamic Groovy execution
SCRIPT_SECURITY_GROOVY_METACLASSmetaClassGroovy metaclass manipulation
SCRIPT_SECURITY_JAVA_TYPEjava.type(, Packages.Host class lookup (GraalVM JS)

Configuration

Script Guard is configured via Spring Boot application properties under the eximeebpms.bpm.script-security prefix:

eximeebpms:
  bpm:
    script-security:
      mode: ENFORCE
      allowlisted-process-definition-keys:
        - my-trusted-process
        - legacy-migration-process
      violation-store-size: 1000
      retention-days: 30
PropertyTypeDefaultDescription
modeENFORCE | AUDIT | DISABLEDENFORCEEnforcement mode on startup. Can be changed at runtime via the REST API without restarting.
allowlisted-process-definition-keyslistemptyProcess definition keys whose scripts skip all security checks. Can be extended at runtime via the REST API.
violation-store-sizeinteger1000Maximum number of violations kept in the in-memory ring buffer. Older entries are evicted when the limit is reached.
retention-daysinteger0Number of days to retain violation records in the database. 0 disables automatic cleanup.

Script Guard stores its runtime configuration and violation records in the database. The ACT_RU_SCRIPT_VIOLATION table is created automatically during the schema migration (Community Edition: shipped in 1.3.0; Enterprise Edition: shipped in 1.2.13-ee).

Allowlisting Process Definitions

Processes that intentionally use constructs blocked by the policy can be placed on an allowlist. Scripts belonging to allowlisted processes skip all security checks.

The allowlist can be set statically in application.yml (see Configuration) or updated at runtime via the REST API. Runtime updates are stored in the ACT_GE_PROPERTY table and propagate to all engine nodes within 30 seconds.

Allowlisting disables all Script Guard checks for the listed processes. Prefer enabling AUDIT mode first to identify which patterns are actually used before committing to an allowlist.

Violation Monitoring

Whenever a script triggers a rule — in either ENFORCE or AUDIT mode — Script Guard records a violation event containing:

  • Timestamp of the violation
  • Process definition key and activity ID of the offending script
  • Scripting language (e.g., groovy, javascript)
  • Source type: INLINE_SOURCE, DYNAMIC_SOURCE, RESOURCE, DYNAMIC_RESOURCE, EXPRESSION, or UNKNOWN
  • Script origin: USER, PROCESS_APPLICATION, or PLATFORM
  • Rule code (e.g., SCRIPT_SECURITY_RUNTIME_EXEC) and a human-readable reason

Violations are persisted in the ACT_RU_SCRIPT_VIOLATION table and can be queried via the REST API. The in-memory ring buffer holds up to violation-store-size recent entries; the total count is always available independently.

If the eximeebpms-bpm-monitor extension is used, violations are also exposed as Micrometer meters — see Application Monitoring.

REST API

The Script Guard REST API is available at:

  • /engine-rest/script-security — for the default engine
  • /engine-rest/engine/{name}/script-security — for a named engine

All endpoints require the ALL permission on the SYSTEM resource (i.e., the eximeebpms-admin role). Requests without this permission receive an HTTP 403 response.

Get Configuration

Returns the current Script Guard configuration.

GET /script-security/config

Response (200 OK):

{
  "mode": "ENFORCE",
  "allowlistedKeys": ["my-trusted-process"]
}
FieldTypeDescription
modestringCurrent enforcement mode: ENFORCE, AUDIT, or DISABLED.
allowlistedKeysarray<string>Process definition keys that skip all security checks.

Update Configuration

Updates the Script Guard configuration at runtime. Changes take effect on all engine nodes within 30 seconds without a restart.

PUT /script-security/config

Request body:

{
  "mode": "AUDIT",
  "allowlistedKeys": ["my-trusted-process", "legacy-migration-process"]
}
FieldTypeRequiredDescription
modestringyesNew enforcement mode: ENFORCE, AUDIT, or DISABLED.
allowlistedKeysarray<string>noUpdated allowlist — replaces the existing list entirely.

Response (200 OK): the updated configuration (same structure as Get Configuration).

List Violations

Returns recent Script Guard violations in descending timestamp order.

GET /script-security/violations

Query parameters:

ParameterTypeDefaultDescription
firstResultinteger0Pagination offset.
maxResultsinteger50Maximum number of results returned.

Response (200 OK):

[
  {
    "timestamp": "2026-01-15T10:30:00.000Z",
    "processDefinitionKey": "payment-process",
    "activityId": "scriptTask_1",
    "language": "groovy",
    "sourceType": "INLINE_SOURCE",
    "origin": "PROCESS_APPLICATION",
    "ruleCode": "SCRIPT_SECURITY_RUNTIME_EXEC",
    "reason": "Access to Runtime.getRuntime() is forbidden"
  }
]
FieldTypeDescription
timestampstringISO 8601 timestamp of the violation.
processDefinitionKeystringKey of the process definition containing the offending script.
activityIdstringID of the BPMN element that triggered the violation.
languagestringScripting language (e.g., groovy, javascript).
sourceTypestringINLINE_SOURCE, DYNAMIC_SOURCE, RESOURCE, DYNAMIC_RESOURCE, EXPRESSION, or UNKNOWN.
originstringUSER, PROCESS_APPLICATION, PLATFORM, or UNKNOWN.
ruleCodestringMachine-readable rule code that matched (see Blocked Patterns).
reasonstringHuman-readable description of why the script was flagged.

Get Violation Count

Returns the total number of violations recorded since the engine started.

GET /script-security/violations/count

Response (200 OK):

{
  "count": 42
}

External Validation Module

The same rule set Script Guard enforces inside the engine is also available as a standalone library, with no dependency on the process engine. Add it to a process-design tool, a CI pipeline, or any other pre-deployment tooling to check a script or expression before ever attempting to deploy the process definition that contains it — instead of only finding out from a rejected deployment.

Adding the Dependency

<dependency>
  <groupId>org.eximeebpms.commons</groupId>
  <artifactId>eximeebpms-commons-script-guard-rules</artifactId>
</dependency>

Usage

ScriptSecurityRuleSet ruleSet = DefaultScriptSecurityRuleSet.INSTANCE;
ScriptValidationResult result = ruleSet.validate(scriptSource, ScriptOrigin.USER);

if (!result.isClean()) {
  for (ScriptSecurityRuleMatch match : result.getMatches()) {
    System.out.println(match.getRuleCode() + ": " + match.getReason());
  }
}

ScriptValidationResult reports rule matches only — it never returns an ENFORCE/AUDIT/DENY outcome. Whether a match actually blocks deployment depends on the target engine instance’s own configured mode, which this module has no way to know. Use it to catch a violation before deploying; the engine’s own enforcement is still authoritative at deploy time.

Rule codes and reasons reported here are identical to the ones in Blocked Patterns and the ones recorded in Violation Monitoring — the engine and this module share one rule set, so the two can never disagree.

Recommended Rollout

  1. Audit first — enable Script Guard with mode AUDIT. Existing processes continue to run but violations are recorded.
  2. Review violations — use the REST API to identify which processes and patterns are flagged.
  3. Allowlist trusted processes — for processes that intentionally use blocked patterns, add them to the allowlist via the REST API.
  4. Enforce — switch mode to ENFORCE once all violations are resolved or allowlisted.

On this page