
Proof-of-concept reproducers for Apache Camel camel-google-storage path traversal (CVE-2026-66907), demonstrating arbitrary file write via downloadFileName, with affected and fixed version details.
downloadFileName path traversalRunnable proof-of-concept reproducers for the same Apache Camel vulnerability, one per runtime:
Both are affected versions (the issue is fixed in 4.14.9 / 4.18.4 / 4.22.0), and both demonstrate the identical
defect: the camel-google-storage consumer downloads bucket objects to the local filesystem when downloadFileName
is a directory, building the local target by appending the remote object name to it
(downloadFileName + "/${file:name}"). The ${file:name} token returns the object name verbatim (unlike
${file:onlyname}, which strips the path), and the result was passed to new File(result) /
blob.downloadTo(file.toPath()) with no normalization and no check that the destination stayed inside the
configured directory. The object name is not route-controlled — the consumer lists the bucket and downloads every
object — so an object whose name contains ../ segments is written outside downloadFileName (CWE-22, path
traversal → arbitrary file write).
Each subdirectory is self-contained (its own Dockerfile, docker-compose.yml bringing up a
fake-gcs-server emulator, and README). In short, for either:
cd camel-spring-boot # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
Expected output on an affected build (both variants):
Files inside the intended download directory /app/downloads:
- report.txt
File written OUTSIDE it, at /tmp/pwned-66907.txt: true
content: PWNED via path traversal — CVE-2026-66907
>>> PROVEN: the object name's ../ segments escaped the configured downloadFileName directory ... : true
Advisory: https://camel.apache.org/security/CVE-2026-66907.html
The consumer now normalizes the resolved path and asserts it stays within the configured downloadFileName
directory (via GoogleCloudStorageFileNameHelper.assertWithinDirectory), rejecting object names that would escape
it.
The docker-compose.yml runs fake-gcs-server with -backend memory. Object names are then kept as opaque map
keys, so a name containing ../ is preserved; the default filesystem backend would resolve the ../ and the
object would not be listable.
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 written file is a
benign marker under /tmp. Do not use this material against systems you do not own or operate.
| Runtime | Directory | Stack |
|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-google-storage 4.18.2 |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.36.0 + Camel Quarkus 3.36.0 (bundles Camel 4.20.0) |
| Property | Value |
|---|
| Component | camel-google-storage (Spring Boot: camel-google-storage-starter; Quarkus: camel-quarkus-google-storage) |
| CWE | CWE-22 (Improper Limitation of a Pathname to a Restricted Directory — Path Traversal) |
| Attack vector | A bucket object whose name contains ../ segments, downloaded by the consumer with downloadFileName set to a directory |
| Impact | Arbitrary file write outside the configured download directory |
| Affected Versions | From 4.0.0 before 4.14.9, from 4.15.0 before 4.18.4, from 4.19.0 before 4.22.0 |
| Fixed Versions | 4.14.9, 4.18.4, 4.22.0 |
| JIRA | CAMEL-24279 |
| Credit | n0mi1k |