
Runnable proof-of-concept reproducer for CVE-2026-95628, an absolute-path validation gap in Apache Camel camel-docling, with Spring Boot and Quarkus harnesses and fix verification.
validatePathSafety did not reject absolute paths (incomplete fix of CVE-2026-40047)Runnable proof-of-concept reproducer for the Apache Camel vulnerability where the custom-argument path check
that CVE-2026-40047's fix introduced looked only
for relative traversal. It rejected a value containing ../ and a value whose normalized form still held
a .. element — but it never checked whether a value was an absolute path, and an absolute path without
traversal segments contains neither.
| Runtime | Directory | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-docling 4.22.1 |
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0) |
cd camel-spring-boot # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until [ "$(curl -s http://localhost:8080/exploit/ready)" = "Started" ]; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down
Output on an affected build (identical on both runtimes):
1) A relative traversal value, which the CVE-2026-40047 fix does reject
header CamelDoclingCustomArguments = [--artifacts-path, ../../../../etc]
REJECTED by Camel: IllegalArgumentException: Custom argument at index 1 contains a relative path traversal sequence
2) Traversal hidden behind redundant separators - also rejected (normalized first)
header CamelDoclingCustomArguments = [--artifacts-path, models/./../../../../etc]
REJECTED by Camel: IllegalArgumentException: Custom argument at index 1 contains a relative path traversal sequence
3) An ABSOLUTE path, which contains no traversal sequence at all
header CamelDoclingCustomArguments = [--artifacts-path, /etc]
argv docling received: --artifacts-path /etc --to md --ocr-lang en --output /tmp/docling-... /tmp/docling-.../docling-....tmp
4) The same, attached to the flag after an equals sign
header CamelDoclingCustomArguments = [--artifacts-path=/root/.ssh]
argv docling received: --artifacts-path=/root/.ssh --to md --ocr-lang en --output /tmp/docling-... /tmp/docling-.../docling-....tmp
>>> PROVEN: ...
Probes 1 and 2 show the CVE-2026-40047 fix doing its job. Probes 3 and 4 are the gap: the flag is on that
fix's allowlist (--artifacts-path tells docling where to find its model artifacts), and the value sails
through in both argument forms — a separate list element following the flag, and attached after an =. A
party able to choose the custom arguments could therefore point the docling process at any directory the
Camel process can access, outside the working directory the check was meant to keep path values in, which is
exactly the outcome the earlier fix set out to prevent.
No docling installation needed. The flaw is in the command line Camel builds, so the endpoint's
doclingCommand option points at a recording stand-in for the CLI that writes the argument vector it was
handed to a file. The real DoclingProducer, the real validateCustomArguments() and the real
validatePathSafety() run; only the external tool is replaced.
Only CLI mode, which is the default, passes custom arguments to docling.
CamelDoclingCustomArguments belongs to the Camel header namespace, which consumers applying Camel's
default header filtering — the JMS and Kafka consumers, for instance — strip from incoming messages. The
issue is therefore reached where a route forwards externally influenced values into the header, or where a
consumer maps incoming headers without that filtering.
| Property | Value |
|---|---|
| Component | camel-docling (DoclingProducer.validatePathSafety()) |
| CWE | CWE-22 (Improper Limitation of a Pathname to a Restricted Directory) |
| Severity | Medium |
| Attack vector | An absolute path as the value of an allowlisted path-like flag in CamelDoclingCustomArguments |
| Impact | Point the docling process at any directory the Camel process can access |
| Affected Versions | From 4.15.0 before 4.18.5, from 4.19.0 before 4.22.2 |
| Fixed Versions | 4.18.5, 4.22.2, 4.23.0 |
| JIRA | CAMEL-24893 |
| Credit | Zhixi "Jace" Sun, independent security researcher |
Advisory: https://camel.apache.org/security/CVE-2026-95628.html
Related: this is an incomplete fix of CVE-2026-40047, and the same component's output-path header is CVE-2026-95629.
validatePathSafety now also rejects a path-like custom-argument value that is an absolute path, failing
the exchange with an IllegalArgumentException saying the argument must not be an absolute path. Because
the check sits in the shared helper that validates every path-like value, both argument forms are covered.
Fixed on main in apache/camel#26738 (fd3bc8e7), backported
to camel-4.22.x in #26743 (e9233c37) and to camel-4.18.x
in #26744 (59d30af1).
Set camel.version to 4.22.2 and run it again. Verified against 4.22.1 → 4.22.2:
3) An ABSOLUTE path, which contains no traversal sequence at all
REJECTED by Camel: IllegalArgumentException: Custom argument at index 1 must not be an absolute path
4) The same, attached to the flag after an equals sign
REJECTED by Camel: IllegalArgumentException: Custom argument at index 0 must not be an absolute path
>>> NOT reproduced: the absolute path was rejected too.
Do not build CamelDoclingCustomArguments from values that originate outside the deployment; strip that
header from messages arriving from outside before they reach a docling endpoint; and make sure consumers
that map incoming headers drop the Camel header namespace, so only the route chooses the custom arguments.
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. Do not use this material against systems you do not own or operate.