
Runnable Spring Boot proof-of-concept for CVE-2026-83531, demonstrating expression-language injection in Apache Camel's dynamic-router-control endpoint and verifying the fix.
Runnable proof-of-concept reproducer for the Apache Camel vulnerability where the dynamic-router-control endpoint
took the subscription predicate and the name of the language used to compile it from the incoming
message (the predicate / expressionLanguage fields of a DynamicRouterControlMessage, or the
CamelDynamicRouterPredicate / CamelDynamicRouterExpressionLanguage headers). The service then resolved that
language from the CamelContext and compiled the expression into a Predicate, with no allow-list and no
opt-in. The compiled predicate was evaluated against every exchange routed through the channel — so any actor able
to send a message onto a transport whose route forwards it to a control endpoint could supply an expression of their
choosing, evaluated with the privileges of the Camel process. Any language on the classpath could be selected,
including simple, which is always present and was the default.
Camel Spring Boot only. There is no
camel-quarkus-dynamic-routerextension, so this reproducer cannot be run on Camel Quarkus.
| Runtime | Directory | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-dynamic-router 4.22.0 (affected; fixed 4.22.1) |
The app sets up a Dynamic Router channel test (direct:start → dynamic-router://test). The attacker sends a
subscribe control message carrying an attacker-chosen predicate expression and language:
CamelDynamicRouterPredicate = ${bean:detonator?method=detonate}
CamelDynamicRouterExpressionLanguage = simple
Then one message is routed through the channel, which evaluates the subscription predicate. On the affected build
the expression runs, invoking detonator.detonate() — a benign stand-in for any no-argument registry method an
attacker could reach (and any language, e.g. Groovy, enables arbitrary code). On the fixed build the control
endpoint refuses to take the predicate/language from the message.
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
Expected output on the affected build:
Subscription accepted.
>>> PROVEN: the attacker-supplied predicate expression was compiled and evaluated, invoking
>>> detonator.detonate() with the privileges of the Camel process ...
On the fixed build the subscribe is rejected with IllegalArgumentException: The subscription predicate expression, and the language used to compile it, cannot be taken from a control message. ... set 'allowPredicateFromMessage=true' ....
| Property | Value |
|---|---|
| Component | camel-dynamic-router (dynamic-router-control endpoint) |
| CWE | CWE-94 (Code Injection), CWE-917 (Expression Language Injection) |
| Severity | HIGH |
| Attack vector | A control message (subscribe/update) supplying a predicate expression and language, on a transport whose route forwards it to a dynamic-router-control endpoint |
| Impact | Evaluation of an attacker-chosen expression (any classpath language) with the Camel process's privileges — code execution |
| Affected Versions | From 4.4.0 before 4.18.5, from 4.19.0 before 4.22.1 |
| Fixed Versions | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24576 |
| Credit | Leon Zlobecki |
Advisory: https://camel.apache.org/security/CVE-2026-83531.html
The predicate expression and its language are no longer taken from the control message by default: a control message
that supplies them is rejected unless the route author explicitly opts in with allowPredicateFromMessage=true on
the dynamic-router-control endpoint. The intended path is to configure predicate and expressionLanguage on the
endpoint URI (route-author-controlled), as releases before 4.4.0 did.
Do not forward externally originated messages to a dynamic-router-control endpoint; manage subscriptions only from
route-author-controlled endpoints, and restrict the transports that can reach the control channel.
This repository is published for educational and defensive purposes: to help Apache Camel users understand the vulnerability, verify whether they are affected, and confirm that upgrading resolves it. The payload is a benign marker bean. Do not use this material against systems you do not own or operate.