
Runnable proof-of-concept for CVE-2026-78164, demonstrating secret leakage when Apache Camel HTTP producers resolve property placeholders in attacker-supplied CamelHttpUri headers.
Runnable proof-of-concept reproducer for the Apache Camel vulnerability where the HTTP producer families let an
inbound message override the endpoint URI through the CamelHttpUri and CamelRestHttpUri headers, and then passed
that message-supplied string through CamelContext.resolvePropertyPlaceholders() before using it.
Property-placeholder resolution is a configuration-resolution facility, not a URI-parsing step. It reaches
operating-system environment variables, JVM system properties, every PropertiesFunction on the classpath
(including the AWS, Azure, GCP, HashiCorp, IBM, CyberArk and Kubernetes secret functions) and — through
camel-bean — the invocation of a no-argument method on any bean in the registry. Applying it to attacker-
influenced Exchange content turns a URI string into a configuration- and bean-evaluation context. A route author
opted into none of this: a plain static to("http://backend/api") was sufficient.
| Runtime | Directory | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-http 4.22.0 (affected; fixed 4.22.1) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.29.0 + camel-quarkus-http 3.29.0 (Camel 4.15.0, affected) |
The behaviour predates the 4.x line (it dates back to camel-http4 / camel-netty4), so every affected release and the Camel 4.15.0 in the latest Camel Quarkus are vulnerable. The fix ships in Camel 4.18.5 / 4.22.1 / 4.23.0; the Spring Boot module runs both the affected build (4.22.0) and the fixed build (4.22.1). No released Camel Quarkus yet bundles a fixed Camel.
The route is a plain static to("http://127.0.0.1:9100/collect") pointing at a local collector. The attacker sets
the CamelHttpUri header to a URI carrying a property-placeholder token — without knowing the secret value, only
naming the key:
CamelHttpUri: http://127.0.0.1:9100/collect?leak={{sys:cve78164.secret}}
The app seeds a JVM system property cve78164.secret to stand in for any configuration value or vault secret. On the
affected build the producer resolves the placeholder before the request goes out, so the collector sees the
secret in the outbound query. On the fixed build the token is forwarded literally.
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
Expected output on the affected build:
Outbound request observed by the collector:
GET /collect?leak=S3CR3T-cve78164-do-not-leak
>>> PROVEN: the {{sys:...}} placeholder in the attacker-supplied CamelHttpUri was resolved,
>>> expanding the secret 'S3CR3T-cve78164-do-not-leak' into the outbound request.
On the fixed build the collector instead sees GET /collect?leak={{sys:cve78164.secret}} (literal, not resolved).
| Property | Value |
|---|---|
| Component | camel-http / camel-http-common / camel-vertx-http / camel-undertow / camel-netty-http |
| CWE | CWE-1336 (Improper Neutralization of Special Elements Used in a Template Engine), CWE-200 (Information Exposure) |
| Severity | HIGH |
| Attack vector | CamelHttpUri / CamelRestHttpUri override header carrying a {{...}} token; the body/headers are not bounded by bridgeEndpoint, and several consumers populate CamelHttpUri from the request line as a reverse-proxy feature |
| Impact | Expansion of environment variables, system properties and vault secrets into the outbound request; no-arg invocation of registry beans; a set/unset config key oracle via the echoed error |
| Affected Versions | From 4.0.0 before 4.18.5, from 4.19.0 before 4.22.1 (behaviour predates 4.x) |
| Fixed Versions | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24418 |
| Credit | [email protected] |
Advisory: https://camel.apache.org/security/CVE-2026-78164.html
The per-message resolvePropertyPlaceholders() call is removed at every affected site, so a {{...}} token that
appears only in CamelHttpUri or CamelRestHttpUri is now treated as a literal part of the URI. Placeholders in the
route's own endpoint URI are unaffected — they are resolved once, at build time, when the endpoint is created.
Strip the override headers at the trust boundary before the producer with removeHeader("CamelHttpUri") and
removeHeader("CamelRestHttpUri"), or set skipControlHeaders=true on camel-http endpoints (the only component
offering that option). bridgeEndpoint=true is not a workaround. Apply a strict inbound HeaderFilterStrategy
on consumers exposed to untrusted senders, and resolve secrets through a vault rather than through env/system
properties a placeholder can name.
This repository is published for educational and defensive purposes: to help Apache Camel users understand the vulnerability, verify whether they are affected, and confirm that upgrading resolves it. The "secret" is an inert local fixture. Do not use this material against systems you do not own or operate.