July 28, 2026
[CVE-2026–56139] Apache Camel Undertow Component — Sensitive Information Exposure via Error…
1. Overview
By Guidancewhite
3 min read
1. Overview
Field Detail CVE ID : CVE-2026–56139 Classification : CWE-209 (Generation of Error Message Containing Sensitive Information) Affected component : camel-undertow (Apache Camel) Affected versions: 4.0.0–4.14.7 / 4.15.0–4.18.2 / 4.19.0–4.20.x Fixed in : 4.14.8 / 4.18.3 / 4.21.0 Disclosed : 2026–07–06
Apache Camel is an integration framework used to connect different systems. camel-undertow is the component that builds HTTP endpoints on top of the lightweight Undertow web server.
This CVE doesn't require any novel exploitation technique. It's a case where a single misconfigured default value leaks internal server information without any special manipulation at all.
2. Safe Behavior vs. Vulnerable Behavior
Camel's HTTP server consumers use a muteException option to decide whether an exception thrown during route processing should be shown to the client.
- muteException = true → the exception is suppressed; only an empty response is returned (safe)
- muteException = false → the full exception stack trace is written directly into the response body (dangerous)
The issue was the default value of this option. camel-http, camel-jetty, camel-servlet, and camel-platform-http all default to true — but camel-undertow alone defaulted to false.
In other words, if a developer used camel-undertow without explicitly setting muteException, the service was unknowingly running in "exception-exposing" mode.
3. Source Code Analysis
3–1. Normal Route Flow
Here's a conceptual reconstruction of how UndertowConsumer handles an incoming request:
// UndertowConsumer processing flow (conceptual reconstruction)
try {
exchange = createExchange(httpExchange);
processor.process(exchange); // route logic runs here; exception may be thrown
} catch (Exception e) {
if (!muteException) {
// default is false, so execution falls into this branch
httpExchange.getResponseSender().send(getStackTraceAsString(e));
} else {
httpExchange.setStatusCode(500);
// response body stays empty
}
}// UndertowConsumer processing flow (conceptual reconstruction)
try {
exchange = createExchange(httpExchange);
processor.process(exchange); // route logic runs here; exception may be thrown
} catch (Exception e) {
if (!muteException) {
// default is false, so execution falls into this branch
httpExchange.getResponseSender().send(getStackTraceAsString(e));
} else {
httpExchange.setStatusCode(500);
// response body stays empty
}
}The core issue is that a single boolean flag, muteException, decides whether the exception gets exposed — and that flag's initial value was set incorrectly. This is the primary root cause.
3–2. The Bigger Problem — Rest DSL Ignores the Setting Entirely
This is where it gets worse. When using Camel's Rest DSL (defining REST APIs with the rest() syntax), response handling goes through a separate class called RestUndertowHttpBinding, and this class constructs itself with muteException hardcoded to false.
// RestUndertowHttpBinding constructor (conceptual reconstruction)
public class RestUndertowHttpBinding extends DefaultUndertowHttpBinding {
public RestUndertowHttpBinding() {
// muteException is fixed to false regardless of user configuration
super(false);
}
}// RestUndertowHttpBinding constructor (conceptual reconstruction)
public class RestUndertowHttpBinding extends DefaultUndertowHttpBinding {
public RestUndertowHttpBinding() {
// muteException is fixed to false regardless of user configuration
super(false);
}
}This is serious because operators who explicitly set the option like below still weren't protected:
undertow:http://0.0.0.0:8080/api?muteException=true
You could believe you'd already secured your endpoint, while the REST-specific code path never even reads that setting. That makes this a much more dangerous class of bug than an ordinary "wrong default" mistake.
4. Attack Scenario
All an attacker needs is a request that triggers an exception somewhere inside the route logic:
Sending a malformed request body Omitting a required parameter or sending the wrong type Sending input that trips up internal logic (a failed DB lookup, a null-pointer condition, etc.)
Any one of these is enough to get a full stack trace back in the response, like:
java.lang.NullPointerException: Cannot invoke "String.length()" ...
at com.company.internal.OrderService.validate(OrderService.java:142)
at com.company.internal.OrderService.process(OrderService.java:88)
at org.apache.camel.processor.CamelInternalProcessor...
Caused by: java.sql.SQLException: Access denied for user 'admin'@'10.0.2.15'
...java.lang.NullPointerException: Cannot invoke "String.length()" ...
at com.company.internal.OrderService.validate(OrderService.java:142)
at com.company.internal.OrderService.process(OrderService.java:88)
at org.apache.camel.processor.CamelInternalProcessor...
Caused by: java.sql.SQLException: Access denied for user 'admin'@'10.0.2.15'
...5. What Can Leak in a Stack Trace
- Credential fragments embedded in exception messages
- Internal hostnames and private IP ranges
- Server filesystem paths
- Library and version information (useful for chaining with other CVEs)
- Class names, package structure, and internal application architecture
It's not remote code execution by itself, but it's a large chunk of reconnaissance data that significantly shortens an attacker's path to further exploitation.
6. Mitigation
Immediate action (before patching)
For normal routes, explicitly set muteException=true:
undertow:http://0.0.0.0:8080/api?muteException=true
or set it globally via a property:
camel.component.undertow.mute-exception=true
However, if you're using Rest DSL, this alone will not fully protect you — because of the hardcoded bug described above.
Root-cause fix (recommended) Stream in use Upgrade to Latest 4.21.0 4.14.x LTS 4.14.8 4.18.x 4.18.3