Safeguard
Vulnerability Analysis•

Camunda 7 CVE-2026-109432: orQueries Expression Bypass, No CE Fix

CVE-2026-109432 lets Camunda 7 task queries run JUEL through orQueries. Fixes are enterprise only and CE 7.24.0 is affected. How it works and what to do.

Safeguard Security Team
37 min read

CVE-2026-109432 lets a caller of the Camunda 7 task query API get a JUEL expression evaluated by placing it inside an orQueries entry, past the switch that normally forbids expressions in ad hoc queries. It affects 7.24.0 before 7.24.14 and 7.23.0 before 7.23.17. Fixed builds are enterprise only, so Community Edition users must lock down the REST API and filter requests.

The CVE record, published on 19 October 2026, says the expression can reach java.lang.Runtime.exec, which means operating system command execution as the account the engine runs under. Both scores in the record are critical: 9.3 under CVSS 4.0 and 9.8 under CVSS 3.1.

This post is for teams still running Camunda 7, and especially Community Edition (CE), where no public fixed build exists. It covers the bug as it reads in the 7.24.0 source, the defaults that decide whether your REST API asks for a password, what to do on each edition, and a request guard for your gateway.

The short answer

If you have a Camunda 7 enterprise subscription, upgrade to 7.24.14 or 7.23.17 or later. If you run Community Edition, there is no public fixed build: the newest release on Maven Central is 7.24.0, which is affected, and Camunda has said CE gets no further releases, including security patches. On CE, take the REST API off untrusted networks, turn on its authentication, reject task queries that carry any *Expression parameter inside orQueries, and run the engine with the least privilege you can. Then decide between an enterprise subscription and migration, and write that decision down.

What happened

All times are UTC. The 2025 entries explain why CE users are in the position they are in; the 2026 entries cover the CVE itself.

Date and time (UTC)EventSource
2025, February (updated July 2025)Camunda extends Camunda 7 Enterprise Edition end of life to 9 April 2030 and confirms that CE's final feature release is 7.24, scheduled for 14 October 2025. After that date, Camunda says, CE gets no further releases, security patches included.Camunda blog, EoL extension announcement
2025-04-01 07:32camunda-engine 7.23.0 artifacts last modified on Maven Central.Maven Central
2025-10-07 08:28camunda-engine 7.24.0 published to Maven Central. Docker Hub latest and run-latest tags were pushed the same morning.Maven Central, Docker Hub
2025-10-14 06:57Maven Central metadata for camunda-engine last updated, with 7.24.0 as both latest and release.Maven Central metadata
2025-11-04camunda/camunda-bpm-platform on GitHub archived by its owner. Its description says Camunda 7 CE is end of life.GitHub
2026-04-06 11:52Docker Hub 7.24.0, run-7.24.0 and tomcat-7.24.0 tags last pushed. They still carry engine 7.24.0.Docker Hub API
2026-08-31The CVE record's "date public" field. The record does not say what happened on that date.CVE record
2026-09-15Camunda security notice 168 fixes a different CVE in 7.24.15 and names "7.24.14 or lower" as affected, so the enterprise 7.24.14 build already existed by this date.Camunda security notices
2026-10-09Camunda security notice 171 fixes two other CVEs in enterprise 7.24.16, the newest Camunda 7 release named on the notices page.Camunda security notices
2026-10-12 15:52CVE-2026-109432 reserved.CVE record
2026-10-19 15:08CVE record published, titled "Camunda Expression Injection via orQueries RCE". It credits the CodeAnt AI Security Research Team as finder.CVE record
2026-10-19 15:58CISA's ADP container adds an SSVC assessment: exploitation "poc", automatable "yes", technical impact "total".CVE record, CISA ADP
2026-10-19 16:17NVD publishes its entry. As of 25 October its status is "Deferred", with no NVD enrichment beyond the CNA's data.NVD API
2026-10-19 18:32GitHub publishes GHSA-mqfw-m4cx-w4jp. It is unreviewed and lists no affected package.GitHub advisory API
2026-10-23 19:30CISA KEV catalog version 2026.10.23 (1,756 entries) does not list CVE-2026-109432.CISA KEV JSON feed
2026-10-25No change to the CVE record since 19 October 16:34. OSV returns no record for the CVE ID. Camunda's public security notices page has no notice for CVE-2026-109432.CVE API, OSV API, Camunda security notices

Affected and fixed versions

LineAffected per CVE recordFixed inWhere the fix isPublic CE builds on this line
7.247.24.0 up to but not including 7.24.147.24.14Camunda enterprise downloads7.24.0 only (Maven Central, Docker Hub). Affected
7.237.23.0 up to but not including 7.23.177.23.17Camunda enterprise downloads7.23.0 only. Affected
7.22 and olderNot listed; the record's default status is "unaffected"Not statedNot statedSee "Where sources differ" below
7.24.0 alpha releasesNot covered by the semver range as writtenNot statedNot stated7.24.0-alpha1 to alpha3. Development builds; do not run them in production

The key fact for CE users: every public build on the 7.23 and 7.24 lines falls inside the affected range, and no public build falls outside it.

Technical details

Identifiers and scores

FieldValueSource
CVECVE-2026-109432CVE record
CNA title"Camunda Expression Injection via orQueries RCE"CVE record
WeaknessesCWE-917 (expression language injection), CWE-78 (OS command injection)CVE record. The GitHub advisory lists only CWE-78
CVSS 4.09.3 critical, CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:NCVE record
CVSS 3.19.8 critical, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HCVE record
CISA SSVCExploitation poc, Automatable yes, Technical Impact total (assessed 2026-10-19 15:58 UTC)CVE record, CISA ADP
GitHub advisoryGHSA-mqfw-m4cx-w4jp, unreviewed, critical (9.3, from the CVSS 4.0 vector), no package listedGitHub advisory API
EPSS0.558 percent, about the 46th percentile, in FIRST's data for 24 OctoberFIRST EPSS API
NVD statusDeferredNVD API
CISA KEVNot listed as of catalog 2026.10.23CISA KEV feed
Finder creditCodeAnt AI Security Research TeamCVE record
Affected productVendor Camunda, product Camunda 7CVE record

Two of those rows matter more than they look. The SSVC "poc" value means CISA's assessors consider a public proof of concept to exist, which matches the CVE record tagging one reference as an exploit write up. And the GitHub advisory lists no package, which means tools that match only on GitHub advisory package data will not flag org.camunda.bpm:camunda-engine for this CVE until someone adds the mapping. Check your scanner's output rather than assuming it knows.

How task query expressions are supposed to be blocked

Camunda's task query API can filter tasks by expressions instead of literal values. In the 7.24.0 REST layer, TaskQueryDto accepts 20 such parameters:

assigneeExpression, assigneeLikeExpression, candidateGroupExpression, candidateGroupsExpression, candidateUserExpression, createdAfterExpression, createdBeforeExpression, createdOnExpression, dueAfterExpression, dueBeforeExpression, dueDateExpression, followUpAfterExpression, followUpBeforeExpression, followUpBeforeOrNotExistentExpression, followUpDateExpression, involvedUserExpression, ownerExpression, processInstanceBusinessKeyExpression, processInstanceBusinessKeyLikeExpression, updatedAfterExpression.

These are evaluated by the engine's expression manager, the same JUEL machinery that runs expressions inside BPMN process definitions. JUEL can call methods on objects it can reach, which is why an expression that should only compute "tomorrow" can, in the wrong hands, reach the Java runtime.

Because that is powerful, the engine splits queries into two kinds:

  • Ad hoc queries are queries built from outside a command, which includes every REST call. In AbstractQuery.java at 7.24.0, the constructor that takes a CommandExecutor attaches AdhocQueryValidator. A comment there says all queries created with a dedicated command executor are treated as ad hoc.
  • Stored queries are the queries saved inside filters. They get StoredQueryValidator.

Each validator checks one switch on the process engine configuration. In ProcessEngineConfigurationImpl.java at 7.24.0, the defaults are:

protected boolean enableExpressionsInAdhocQueries = false;
protected boolean enableExpressionsInStoredQueries = true;

So by default, an expression in a REST task query should fail with the error "Expressions are forbidden in adhoc queries", while an expression saved in a filter is allowed. The ad hoc validator is the control that CVE-2026-109432 gets around.

Where the check falls through

A task query can carry OR branches. The Java API builds each branch with TaskQueryImpl.or(). The REST API takes an orQueries list on the task query body or query string and builds each branch in TaskQueryDto.applyFilters(). Here is the sequence in 7.24.0:

  1. In TaskQueryDto.applyFilters(), each entry of orQueries becomes new TaskQueryImpl(), is marked active as an OR branch, has its filters applied from the DTO, and is added to the parent with addOrQuery(). The Java API's or() also calls new TaskQueryImpl().
  2. TaskQueryImpl has two constructors. The one with no arguments does nothing. Only the one that takes a CommandExecutor calls the AbstractQuery constructor that adds AdhocQueryValidator. So every OR branch starts with an empty validator set.
  3. When the query runs, AbstractQuery.evaluateExpressionsAndExecuteList() and evaluateExpressionsAndExecuteCount() call validate() and then evaluateExpressions() on the base query. The base query has the ad hoc validator, so a top level expression is rejected.
  4. TaskQueryImpl.executeList() and executeCount() then call ensureOrExpressionsEvaluated(). That method loops over the OR branches, skipping the first entry (the base query), and calls validate() and evaluateExpressions() on each.
  5. validate() iterates over the branch's validators. There are none, so it returns. evaluateExpressions() then hands each stored expression string to the expression manager and calls getValue().

The CVE record describes the same gap from the validator's side: AdhocQueryValidator.validate() does not check the expression maps of the sub queries in orQueries. Both descriptions lead to the same place. The check exists and runs on the base query, and nothing runs it on the branches.

The bug class is a familiar one. A safety property was attached in one constructor, and a second construction path, used for a less common feature, skipped it. A test that sent the same expression at the top level and inside an OR branch, and expected the same rejection, would have caught it.

Why the stored query default matters too

The stored query switch is not part of this CVE, but it belongs in the same review. With enableExpressionsInStoredQueries at its default of true, a user allowed to create or update a filter can save a query with expressions, and the engine evaluates them when the filter runs. That is intended behavior, gated by Camunda's authorization model. If none of your filters use expressions, set it to false; if they do, keep filter create and update permissions narrow.

Authentication defaults in the distributions

The CVE text says "authenticated users", but whether your REST API authenticates anyone depends on how it was deployed:

  • Tomcat distribution. In the 7.24.0 source at engine-rest/assembly-jakarta/src/main/runtime/tomcat/webapp/WEB-INF/web.xml, the HTTP Basic authentication filter (ProcessEngineAuthenticationFilter with HttpBasicAuthenticationProvider) and its mapping to /* sit inside an XML comment. Deployed as shipped, the REST application does not ask for credentials.
  • Camunda Run. In the 7.24.0 source, CamundaBpmRunAuthenticationProperties declares boolean enabled; with no initializer, so authentication for the Run REST API is off unless you set camunda.bpm.run.auth.enabled: true.
  • Spring Boot applications that include camunda-bpm-spring-boot-starter-rest get whatever security your application configures around the REST endpoints. Nothing about this CVE changes that, so check your own security configuration.

An unauthenticated REST API turns "an authenticated user can run commands" into "anyone who can reach the port can run commands". That is the single most important thing to check today.

What older lines look like in the source

We read TaskQueryImpl.java at tags 7.17.0, 7.20.0 and 7.22.0. In all three, or() builds each branch with new TaskQueryImpl(), and ensureOrExpressionsEvaluated() has the same body as in 7.24.0. The CVE record lists only the 7.23 and 7.24 lines and marks everything else "unaffected" by default. We have not tested older lines and are not claiming they are exploitable. We are saying the public record does not explain why they would be safe, and older lines are out of community support anyway. Treat them as needing review, not as cleared.

Exploitation status and indicators

As of 25 October there is no public report of exploitation in the wild, and the CVE is not in CISA's KEV catalog. CISA's SSVC assessment says a proof of concept exists. No official source has published indicators of compromise such as IP addresses, hashes or user agents for this CVE, so there are none to list.

What you can look for is behavior:

  • Requests to /task, /task/count or filter endpoints that carry orQueries with any parameter ending in Expression.
  • Engine log lines containing "Expressions are forbidden in adhoc queries" from unexpected clients, which can mean someone tried the top level first.
  • Engine log lines containing "Unable to resolve expression", which the engine raises when an expression fails to evaluate.
  • Child processes of the engine's Java process that your process definitions do not explain, such as shells or download tools.

Where sources differ

  • Authenticated or not. The CVE description says "authenticated users". Both CVSS vectors in the same record say PR:N, no privileges required. The difference is probably the deployment default described above: an API without authentication has no "authenticated user" to require. Plan for the PR:N case unless you have confirmed that authentication is on.
  • Dates. The record's public date is 31 August 2026, the ID was reserved on 12 October, and the record was published on 19 October. The record does not explain the August date.
  • Older versions. The record marks unlisted versions "unaffected" by default. The 7.17.0, 7.20.0 and 7.22.0 source we read has the same OR branch construction. That is a gap in the record's explanation, not proof either way.
  • Weakness IDs. The CVE record lists CWE-917 and CWE-78. The GitHub advisory lists only CWE-78.
  • Vendor notice. The CVE record points to Camunda's enterprise download page as the patch reference. Camunda's security notices page, which lists its own advisories with affected and fixed versions, had no entry for this CVE on 25 October.
  • Package mapping. The CVE record names vendor and product, not Maven coordinates. The GitHub advisory lists no package. OSV had no record on 25 October. Scanners that need a package name to match may say nothing.

Who is affected

DeploymentExposureFirst move
CE 7.23.0 or 7.24.0, REST API reachable from untrusted networks, authentication offHighest. Anyone who can reach the port can send the requestBlock network access today, then turn on authentication
CE 7.23.0 or 7.24.0, REST API internal, authentication onAny account that can query tasks, plus anything that can impersonate oneRequest guard, least privilege, and account review
CE embedded engine with no REST APIOnly callers of the Java task query API inside your application; the record's ad hoc check also applies thereConfirm no code path passes untrusted input into or() branches
Enterprise 7.24.x before 7.24.14 or 7.23.x before 7.23.17Same as CE until upgradedUpgrade
Enterprise 7.24.14 or 7.23.17 and laterFixed per the CVE recordConfirm the running version; on 7.24, move to the newest patch (7.24.16 per Camunda's 9 October notice)
Camunda 8Not named in the CVE recordNothing for this CVE
Camunda 7.22 and olderNot listed; see aboveReview, and plan to leave the line

Why Community Edition users can't just upgrade

CheckWhat it shows
camunda/camunda-bpm-platform on GitHubArchived by the owner on 4 November 2025. Description begins "Camunda 7 CE is End of Life (EoL)". Newest tag 7.24.0
org.camunda.bpm:camunda-engine on Maven CentralLatest and release 7.24.0. No 7.23.x or 7.24.x patch releases
org.camunda.bpm.springboot:camunda-bpm-spring-boot-starter-rest on Maven CentralLatest and release 7.24.0
camunda/camunda-bpm-platform on Docker HubHighest engine version tags are 7.24.0 variants, last pushed 6 April 2026. The 7.22.0 and 7.23.0 tags were pushed again on 22 July 2026 under the same version numbers
Camunda's public Artifactory repositoryShows only 7.24.0 snapshots for camunda-engine. The enterprise repository returns HTTP 401 without credentials
Camunda's EoL announcementAfter the final 7.24 feature release, CE gets "no further releases, including security patches"

Camunda kept its promise in both directions: enterprise customers get patch releases and CE gets none. For a team running CE in production, the options are an enterprise subscription, a migration, or living with compensating controls for as long as the migration takes. The rest of this post assumes you will need controls for at least a few weeks whatever you choose.

What to do now

1. Find every Camunda 7 engine you run

Start with build files, then running systems, then images. An engine can arrive through the Spring Boot starter, a WAR, a Tomcat or WildFly distribution, Camunda Run, or a base image someone forgot about.

Maven projects:

mvn -q dependency:tree -Dincludes=org.camunda.bpm:camunda-engine
mvn -q dependency:tree -Dincludes=org.camunda.bpm.springboot

Gradle projects:

./gradlew dependencyInsight --dependency camunda-engine --configuration runtimeClasspath

On hosts and inside unpacked applications:

find / -xdev -name 'camunda-engine-*.jar' 2>/dev/null
# Spring Boot fat JARs keep dependencies under BOOT-INF/lib
for j in $(find /opt /srv /app -name '*.jar' 2>/dev/null); do
  unzip -l "$j" 2>/dev/null | grep -q 'camunda-engine-7' && echo "$j"
done

A running REST API reports its version:

curl -s http://localhost:8080/engine-rest/version
# Camunda Run and some setups use the /engine-rest prefix; Spring Boot apps may differ

Container images:

docker image ls --format '{{.Repository}}:{{.Tag}}' | grep -i camunda
docker run --rm --entrypoint sh camunda/camunda-bpm-platform:run-7.24.0 \
  -c 'find / -name "camunda-engine-*.jar" 2>/dev/null'

Note the edition too. Enterprise builds come from Camunda's enterprise repository and downloads. Anything resolved from Maven Central or pulled from the public Docker Hub images is CE.

2. Enterprise customers: upgrade

Move to 7.24.14 or 7.23.17 or later from Camunda's enterprise downloads or repository. On the 7.24 line, go straight to the newest patch rather than the minimum: Camunda's notices page names 7.24.15 (15 September) and 7.24.16 (9 October) as fixes for other CVEs, so stopping at 7.24.14 leaves those open. Then confirm with the /version endpoint that the running engine is the one you deployed. Upgrading does not remove the need for the rest of this list: authentication and least privilege are worth having on any version.

3. Community Edition: take the REST API off untrusted networks

If only your own services call the REST API, there is no reason for it to listen on a public address. Bind it to an internal interface or network, and put it behind the gateway your services already use. For a Camunda Run deployment, check server.address and any port publishing in your container setup. For Tomcat, check the connector's address attribute in server.xml and your firewall or security group rules.

A quick external check from outside your network:

curl -s -o /dev/null -w '%{http_code}\n' https://your-host.example/engine-rest/version
# 200 without credentials means the REST API is reachable and unauthenticated

4. Turn on authentication

For the Tomcat distribution, uncomment the camunda-auth filter and its filter-mapping in the REST application's WEB-INF/web.xml, then restart. The block looks like this in the 7.24.0 source once uncommented:

<filter>
  <filter-name>camunda-auth</filter-name>
  <filter-class>org.camunda.bpm.engine.rest.security.auth.ProcessEngineAuthenticationFilter</filter-class>
  <async-supported>true</async-supported>
  <init-param>
    <param-name>authentication-provider</param-name>
    <param-value>org.camunda.bpm.engine.rest.security.auth.impl.HttpBasicAuthenticationProvider</param-value>
  </init-param>
  <init-param>
    <param-name>rest-url-pattern-prefix</param-name>
    <param-value></param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>camunda-auth</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

For Camunda Run, set the property in configuration/default.yml or your production YAML:

camunda.bpm.run.auth.enabled: true

Then verify it:

curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080/engine-rest/task
# expect 401 without credentials

Authentication narrows who can reach the bug, it does not close it. After you turn it on, list who can query tasks. Service accounts with broad task access and shared demo users are the usual surprises. If Camunda's authorization checks are not enabled on the engine, any authenticated user can query tasks.

5. Reject expressions inside orQueries at the edge

Legitimate clients rarely send expressions inside OR branches. The base query check already rejects top level expressions by default, so the gap is narrow and easy to describe: any parameter whose name ends in Expression, anywhere under orQueries.

This function checks a request body or query string and returns reasons to reject it. It is meant for a gateway or proxy hook; the command line part runs it on captured requests. Standard library only.

#!/usr/bin/env python3
"""Flag Camunda 7 task-query requests that put expressions inside orQueries.

CVE-2026-109432: the ad hoc expression check runs on the base task query but
not on its orQueries, so a *Expression parameter there is evaluated anyway.
Use check() in a gateway or proxy hook, or run this file on captured request
bodies. Standard library only.

Usage: python3 orquery_guard.py request1.json [request2.json ...]
"""
import json
import sys
from urllib.parse import parse_qs


def expression_keys(obj, path=""):
    """Yield (path, key) for every key ending in 'Expression' under obj."""
    if isinstance(obj, dict):
        for k, v in obj.items():
            here = f"{path}.{k}" if path else k
            if k.endswith("Expression"):
                yield here, k
            yield from expression_keys(v, here)
    elif isinstance(obj, list):
        for i, v in enumerate(obj):
            yield from expression_keys(v, f"{path}[{i}]")


def check(body="", query_string=""):
    """Return a list of reasons to reject the request (empty means allow)."""
    docs = []
    if body.strip():
        try:
            docs.append(json.loads(body))
        except json.JSONDecodeError:
            pass
    for value in parse_qs(query_string).get("orQueries", []):
        try:
            docs.append({"orQueries": json.loads(value)})
        except json.JSONDecodeError:
            return ["orQueries query parameter is not valid JSON"]
    reasons = []
    for doc in docs:
        for where, key in expression_keys(doc):
            if "orQueries" in where:
                reasons.append(f"{key} inside {where}")
    return reasons


if __name__ == "__main__":
    status = 0
    for path in sys.argv[1:]:
        req = json.load(open(path))
        body = req.get("body", "")
        if not isinstance(body, str):
            body = json.dumps(body)
        reasons = check(body, req.get("query", ""))
        print(f"{path}: {'REJECT ' + '; '.join(reasons) if reasons else 'allow'}")
        status |= bool(reasons)
    sys.exit(status)

We ran it on 25 October on four harmless requests. Two are ordinary task queries, one of them with an expression at the top level, which Camunda's own check already rejects by default. The other two put an expression inside orQueries, once in a JSON body and once in a GET query string. The expressions use Camunda's built in date and user functions, nothing that runs code.

$ python3 orquery_guard.py plain.json base-expr.json or-expr.json or-expr-get.json
plain.json: allow
base-expr.json: allow
or-expr.json: REJECT dueAfterExpression inside orQueries[1].dueAfterExpression
or-expr-get.json: REJECT ownerExpression inside orQueries[0].ownerExpression

Wiring notes:

  • Put it in front of every path that accepts a task query: GET and POST on /task and /task/count, and the filter execution endpoints /filter/{id}/list, /filter/{id}/count and /filter/{id}/singleResult, which accept an extending query in the body. If your REST API is mounted under a prefix such as /engine-rest, include it.
  • If you have turned enableExpressionsInAdhocQueries on, the base level check is gone too. Change the guard to reject every *Expression key, not just the ones under orQueries.
  • Match on parameter names, not expression syntax. JUEL has more than one delimiter form and many ways to write the same call; the parameter names are a fixed list.
  • Reject requests whose JSON fails to parse rather than letting them through. The function above returns a reason for a malformed orQueries query string; in a gateway, treat an unparseable body on these paths the same way.
  • Log rejections with the client identity, so you can tell a misbehaving client from someone probing.

If your gateway cannot run code, most can at least deny a query string containing orQueries together with Expression on these paths. That covers GET requests. POST bodies need body inspection, which usually means a small plugin or a sidecar.

6. Run the engine with the least privilege you can

The expression runs as the engine's operating system user, so that user's reach is the blast radius. On a systemd host, these unit options cut it down without code changes:

[Service]
User=camunda
Group=camunda
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/camunda/logs /opt/camunda/temp
CapabilityBoundingSet=

In containers, run as a non root user, mount the root filesystem read only where the image allows it, drop all capabilities, and give the container an egress policy that allows only the database and the services it calls. Also look at what the engine user can read: database credentials in default.yml, bpm-platform.xml or Spring properties are the first thing an attacker running as that user will look for, so prefer credentials injected at runtime with narrow database grants.

7. Look back for prior use

Search access logs for orQueries combined with Expression on query strings. Most servers do not log POST bodies, so the GET side is what you can see after the fact:

grep -h 'orQueries' /var/log/nginx/access.log* | grep -i 'expression' | head
zgrep -h 'orQueries' /var/log/nginx/access.log*.gz | grep -i 'expression' | head

Search engine logs for the two messages the engine produces around expressions:

grep -h -e 'Expressions are forbidden in adhoc queries' -e 'Unable to resolve expression' \
  /opt/camunda/logs/*.log | head

On Linux hosts, list what the engine's Java process has spawned, and consider an audit rule for process execution by the engine user going forward:

pgrep -u camunda java | xargs -I{} ps -o pid,ppid,user,etime,cmd --ppid {}
sudo auditctl -a always,exit -F arch=b64 -S execve -F uid=$(id -u camunda) -k camunda_exec

If you find something you cannot explain, treat the host and the engine's database credentials as exposed and follow your incident process. Our incident response playbook for a compromised dependency covers the order of operations.

Mitigations compared

ControlCloses the bugEffortNotes
Upgrade to 7.24.14 or 7.23.17Yes, per the CVE recordLow for enterprise customersNot available to CE
Network restrictionNo, narrows who can reach itLowMost effective single step for an exposed API
REST authenticationNo, narrows who can reach itLow to mediumDefault off in Tomcat distribution and Camunda Run
Request guard on orQueriesBlocks the known pathMediumNeeds body inspection for POST
Least privilege for the engine userNo, limits the damageMediumWorth doing on any version
enableExpressionsInStoredQueries=falseNo, separate pathLow if filters do not use expressionsRemoves a second route to the expression engine
Patching the CE source yourselfPossiblyHighYou own the build, the tests and every future fix
Migration to Camunda 8 or another engineYes, for this codeHighThe long term answer for CE users

On patching the source yourself: the CE code is Apache 2.0, so a team can build its own engine with a validator added to the OR branches. It makes you the maintainer of a fork of an archived project, and the enterprise fix is not public, so you would be writing your own. If you do, add a test that sends the same expression at the top level and inside an OR branch and expects the same rejection.

What would have helped

An inventory that knows editions and support status

Many teams know they run "Camunda" without knowing which engines are CE, which line they are on, and that the line stopped receiving fixes a year ago. An inventory that records version, edition and the vendor's support status per deployment turns this CVE into a five minute question. Our post on managing end of life software dependencies covers how to keep that list honest.

A plan for the day an end of life component gets a CVE

Camunda announced CE's end of life well in advance. The teams in the best position on 19 October were those that had already chosen: subscribe, migrate, or accept the risk with named controls and an owner. For the controls themselves, see our guide to living with a vulnerability that has no patch.

Secure defaults, checked rather than assumed

Both the Tomcat distribution and Camunda Run ship with REST authentication off, which suits a laptop and not a server. A deployment check that an unauthenticated request to /version returns 401 catches it.

Where Safeguard fits

Safeguard does not change how the Camunda engine validates queries, and nothing here would have prevented this bug. It helps with the operator's problem: knowing where Camunda 7 runs, at which version, and acting on it.

  • Inventory and matching. Safeguard scans repositories, container images and SBOM files (safeguard scan --dir ., safeguard scan --image <name>, safeguard scan --sbom <file>, with JSON results under ./output), including Maven and Gradle dependencies and container layers. The platform shows which projects contain a given component and version, so "which services resolve camunda-engine 7.23.0 or 7.24.0" becomes a query. Matching draws on several vulnerability databases. Because the public package mapping for this CVE is thin, confirm the result against the version table above rather than relying on any single feed.
  • Prioritisation. Reachability analysis helps rank findings by whether your code reaches the vulnerable paths. It cannot tell you whether your REST API has authentication turned on or which networks can reach it, so check those with the commands above.
  • Policies and gates. A policy can fail a build that resolves an affected camunda-engine version, so a new service cannot quietly start on 7.24.0 while you migrate the old ones. A risk acceptance with an owner and an expiry date keeps the exception visible.
  • Changes with approval. The Safeguard CLI's assistant can edit a web.xml, a Run YAML file or a systemd unit, and run your tests, asking before any command that changes something. For enterprise customers it can change the version in pom.xml or build.gradle once your build can reach Camunda's enterprise repository. Autonomous remediation can open fix pull requests where a fixed version is resolvable, and ships switched off by default.

Where Safeguard does not help: it cannot produce a public CE build of Camunda with the fix, it cannot see the network path to an engine it has not scanned, and it cannot tell whether a line in your logs was an attack.

Zero-Day Discovery and Gold

Safeguard's Zero-Day Discovery looks for previously unknown flaws before a CVE exists, in an agentic mode and a deterministic scanner mode, and issues findings as SGZ advisories before they reach public CVE databases. It covers seven package ecosystems. This bug was reported by the researchers credited in the CVE record; Safeguard had no part in finding it.

Gold Open Source at gold.safeguard.sh is free and needs no login. It shows CVSS, EPSS, KEV status, affected and fixed versions and a recommended safe version for a CVE, through the site, a free read API and a CI gate GitHub Action. We have not confirmed that it holds a record for this CVE, so check the site rather than relying on this post. Gold Registry at registry.safeguard.sh provides hardened, signed components and container images held to zero exploitable critical or high CVEs; we make no claim that it carries a fixed Camunda 7 engine. The habit worth taking from both is the one this CVE punishes the lack of: pull patched, signed components from a source someone is still maintaining, and rebuild fast.

Common mistakes

  • Reading "authenticated" in the CVE text and stopping there. If your REST API was deployed from the Tomcat distribution or Camunda Run defaults, there may be no authentication at all. Test it.
  • Looking for 7.24.14 on Maven Central. It is not there and will not be. Enterprise builds come from Camunda's enterprise channel.
  • Assuming the scanner will tell you. The GitHub advisory lists no package, and OSV had no record on 25 October. A clean scan here can mean the feed lacks a mapping, not that you are unaffected.
  • Treating 7.22 and older as safe because the record does not list them. Their source has the same shape, and they get no community fixes either.
  • Guarding only /task. Count endpoints and filter execution endpoints take task queries too.
  • Guarding only GET. Most real clients send task queries as POST bodies.
  • Forgetting embedded engines. A Spring Boot application with the REST starter exposes the same API, often on the application's own port.
  • Leaving the engine with broad file and network access. The expression runs as that user. Its database password is the first thing at risk.
  • Not writing the decision down. An end of life component with a critical CVE (CVSS 4.0 9.3, CVSS 3.1 9.8) needs an owner, a date and a plan in your risk register, not just a line in a scanner backlog.

Open questions

  • What happened on 31 August 2026, the record's public date. The record does not say.
  • Whether lines before 7.23 behave the same way at run time. The source shape matches; the record marks them unaffected by default without explanation.
  • What the enterprise fix changes. It is not public, so this post does not describe it.
  • When GitHub, OSV and NVD will map the CVE to Maven coordinates. Until they do, package based matching may miss it.
  • Why Camunda's own security notices page has no entry for this CVE. The page says notices are published after fixes are available, and the fixed builds already exist, but on 25 October the newest Camunda 7 notice was number 171, of 9 October, for other CVEs.
  • Which release first carried the fix. The CVE record gives 7.24.14 and 7.23.17 as the first fixed builds; Camunda's notice 168 shows 7.24.14 existed by 15 September, which fits the record's 31 August public date, but no source we read ties the two together.

FAQ

Is CVE-2026-109432 being exploited?

There is no public report of exploitation in the wild as of 25 October, and it is not in CISA's KEV catalog. CISA's SSVC assessment in the CVE record says a proof of concept exists and that the attack is automatable. Treat an internet facing, unauthenticated REST API as urgent.

We run CE 7.24.0 from Maven Central. Which version fixes it?

There is no public one. The fixed builds, 7.24.14 and 7.23.17, come from Camunda's enterprise downloads, and 7.24.0 is the newest public release. Mitigate now, then subscribe or migrate.

Does the attacker need an account?

The CVE text says authenticated users; its CVSS vectors say no privileges are required. If your REST API has authentication off, which is the default in the Tomcat distribution and Camunda Run, anyone who can reach it can send the request.

We only use the embedded engine and never expose REST. Are we affected?

The vulnerable code is in the engine, not the REST layer. Your exposure depends on whether any code path lets untrusted input put expressions into OR branches of a task query. If none does, the practical risk is low, but you are still on an unsupported line.

Will a web application firewall catch it?

Only if it inspects JSON bodies and you give it a rule for *Expression keys under orQueries. Generic expression signatures may miss it, because the same expression can be written many ways.

Can we just disable OR queries?

Not with a configuration switch in 7.24.0. You can reject them at the gateway if your clients do not use them. Check your own task list clients and integrations first, and test before you block all orQueries.

We use filters with expressions. Is that the same bug?

No. Filters are stored queries, controlled by enableExpressionsInStoredQueries, which defaults to true by design. They are gated by who may create or update filters. Review those permissions, and turn the switch off if no filter needs expressions.

Did Safeguard find this vulnerability, or have a fixed build first?

No. It was reported by the researchers credited in the CVE record and fixed by Camunda in its enterprise releases. Safeguard's role is helping you find every affected engine and track what you do about it.

Fix it without waiting for upstream

For Camunda 7 CE, the upstream has said it will not ship a public fix, so this is the second gap in its starkest form: the time before any fix you can use exists. The steps below apply to the open source components you build and ship; for a closed enterprise build, the fix still comes from the vendor.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would have helped

These are real product sessions on other examples; none of them shows this Camunda CVE.

The CLI demo shows the assistant fixing a lodash CVE: it reads the finding and advisory, asks before any command that changes something, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, prints a summary and pushes nothing. For a CE deployment here, the same flow applies to configuration: ask it to uncomment the camunda-auth filter in web.xml or set camunda.bpm.run.auth.enabled: true, approve the edit, then approve a restart and the curl check that /engine-rest/task now returns 401.

Click through it at your own pace, or open it full screen.

The desktop app demo shows a CLI session in the conversation list, a request for work on the computer, a folder choice, and Approve or Deny on each command and file edit, ending with an upgrade done and tests passing. Here you would pick the folder of your gateway configuration, ask it to add the orQueries guard to the task and filter routes, and approve each edit and the test run against the four harmless fixtures above.

Click through it at your own pace, or open it full screen.

The Claude demo shows connecting Claude to the Safeguard MCP server with OAuth and choosing which tools Claude can use. Once connected, the estate wide question for this CVE, which projects and images resolve camunda-engine 7.23.0 or 7.24.0, is something you can ask in plain language against the projects already scanned in your account.

Click through it at your own pace, or open it full screen.

To try it on your own projects, download Safeguard and read the CLI documentation. Related reading: finding affected products fast with SBOMs and our October 2026 roundup.

Quick check

Your Camunda 7 configuration leaves enableExpressionsInAdhocQueries at its default. Are you protected from CVE-2026-109432?

No. The setting is enforced by a validator attached to the base task query only. Expressions inside orQueries are evaluated without that check, which is the bug.

You run Camunda Run 7.24.0 from the public Docker image with default settings. Does the REST API ask for credentials?

No. In the 7.24.0 source, Camunda Run's REST authentication is off unless camunda.bpm.run.auth.enabled is set to true. Set it, restart, and confirm an unauthenticated request returns 401.

Why does the guard ignore expressions at the top level of the query?

Because Camunda already rejects them there unless you have enabled ad hoc expressions. The gap is only inside orQueries. If you have turned ad hoc expressions on, extend the guard to reject them everywhere.

Sources

Last reviewed: 25 October 2026. This is a developing story; check the linked advisories for the latest status.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.