# Patch Analysis: camel-docling Variant/Bypass

## Target and fix context

The parent issue is CVE-2026-40047 / GHSA-rpv3-6645-2vqc in Apache Camel `camel-docling`. Apache Camel's public security page lists it as:

> Camel-Docling: Insufficient validation of custom CLI arguments enables argument injection and path traversal in DoclingProducer

Affected range listed by Camel: from 4.15.0 before 4.18.3. Fixed releases listed by Camel: 4.18.3 and 4.19.0. This variant analysis tested 4.18.2 as the affected control, 4.18.3 as the fixed target, and 4.21.0 as a latest-line target.

Resolved release tag identities recorded in `bundle/logs/vuln_variant/fixed_version.txt`:

- `camel-4.18.2`: `3864c200f46aa055a0714a069c702c433aca7097`
- `camel-4.18.3`: `6cc2920f7fd0dc642162aca00288f8dc0c9e37de`
- `camel-4.21.0`: `a84c468557bba6d400fb9675351d7efe64ce01b4`

The exact individual fixing commit was not isolated during this run; the analysis compares the released Maven artifacts and release tags.

## Target security model / threat scope

Apache Camel's `SECURITY.md` points reporters to the Camel security model. The public security page says the model documents who is trusted, where trust boundaries sit, which vulnerability classes are accepted, and which categories are out of scope, including route-author/operator responsibility, explicit opt-ins, unthrottled-route DoS, third-party transitive CVEs not reachable through Camel code, and management surfaces placed on untrusted networks.

This variant stays within the parent issue's accepted scope. The untrusted value crosses an HTTP route boundary into a Camel exchange header and then reaches `DoclingProducer`'s `ProcessBuilder` command construction. It does not claim that a local user choosing arbitrary output paths is a vulnerability by itself; the relevant trust boundary is a deployed route mapping externally influenced HTTP data into docling control headers.

## What the fix changes

The fixed 4.18.3 `DoclingProducer` adds validation around `CamelDoclingCustomArguments` before appending them to the external `docling` command:

- `addCustomArguments(List<String>, Exchange)` reads `CamelDoclingCustomArguments` and calls `validateCustomArguments(customArgs)` before `command.addAll(customArgs)`.
- `validateCustomArguments(List<String>)` rejects null arguments, shell metacharacters, unknown short/long flags, producer-managed flags, and path-like values with traversal.
- `validateLongFlag(String, int)` checks a strict `ALLOWED_DOCLING_FLAGS` allowlist and separately rejects `PRODUCER_MANAGED_FLAGS` such as `--output` / `-o`.
- `validatePathSafety(String, int)` rejects literal `../` and `..\`, then normalizes slash/backslash-containing paths and rejects any normalized path component equal to `..`.

Evidence:
- `bundle/logs/vuln_variant/DoclingProducer_4.18.3_source_snippet.txt`
- `bundle/logs/vuln_variant/javap_docling_4.18.3.txt`

By comparison, 4.18.2 uses a narrow denylist in `validateCustomArguments(...)`: it rejects `--output` / `-o` and literal `../` / `..\`, but it allows unknown flags. 4.16.0 appends custom arguments without this validation.

## Assumptions made by the fix

The fix assumes the dangerous attacker-controlled CLI extension point is primarily `CamelDoclingCustomArguments`. This is why the strict allowlist and path-normalization logic are implemented in `validateCustomArguments(...)` and helper methods invoked from that path.

The fix also assumes producer-managed flags such as `--output` are safe if they are not supplied through custom arguments. However, the value for producer-managed `--output` can itself come from an exchange header: `CamelDoclingOutputFilePath`.

## Code paths / inputs not covered

The fixed and latest code still contain this path:

```java
private void addOutputDirectoryArguments(List<String> command, Exchange exchange, String outputDirectory) {
    String outputFilePath = exchange.getIn().getHeader(DoclingConstants.DOCLING_OUTPUT_FILE_PATH, String.class);
    if (outputFilePath != null) {
        command.add("--output");
        command.add(outputFilePath);
    } else {
        command.add("--output");
        command.add(outputDirectory);
    }
}
```

In both 4.18.3 and 4.21.0 source/bytecode inspected during this run, `addOutputDirectoryArguments(...)` does not call `validatePathSafety(...)`, normalize the header value, or enforce that the normalized output path remains under a configured safe directory. Therefore, an exchange header such as `CamelDoclingOutputFilePath=<safe>/../escaped-output` is appended directly as the value of `--output`.

Primary evidence:
- 4.18.3 source lines in `bundle/logs/vuln_variant/DoclingProducer_4.18.3_source_snippet.txt`: `validatePathSafety(...)` is used under `validateCustomArguments(...)`, while `addOutputDirectoryArguments(...)` appends `CamelDoclingOutputFilePath` directly.
- 4.21.0 source lines in `bundle/logs/vuln_variant/DoclingProducer_4.21.0_source_snippet.txt`: the same pattern remains present.
- Runtime logs show fixed/latest releases pass the traversal value to docling.

## Behavior before and after the fix

### Before fix: 4.18.2

- Unknown custom arguments are accepted by the component and passed to docling.
- `CamelDoclingOutputFilePath` is appended directly to `--output`.
- Runtime variant result: `X-Out: ../escaped-output` maps to `CamelDoclingOutputFilePath=<safe-output>/../escaped-output`, docling receives it, and the proof marker is written outside the safe directory.

### Fixed release: 4.18.3

- Unknown `CamelDoclingCustomArguments` are rejected before docling starts. The control response contains: `Custom argument '--pruva-unknown-flag' is not a recognized docling CLI flag. Only known docling flags are permitted as custom arguments.`
- `CamelDoclingOutputFilePath` is still appended directly to `--output`.
- Runtime variant result: fixed 4.18.3 still invokes docling with `--output <safe-output>/../escaped-output`, and the proof marker is written to the normalized escaped directory.

### Latest tested: 4.21.0

- The custom-argument allowlist remains active.
- The output-header path remains uncovered.
- Runtime variant result: latest-tested 4.21.0 still invokes docling with `--output <safe-output>/../escaped-output`, and the proof marker is written to the normalized escaped directory.

## Completeness assessment

The fix is incomplete for the path-traversal portion of the parent vulnerability. It closes the custom-argument injection path but does not apply the same validation invariant to all path-bearing values that contribute to `docling` argv. In particular, `CamelDoclingOutputFilePath` remains a distinct entry/data path to the same `ProcessBuilder` sink.

The fix should be extended so every path-bearing exchange header that contributes to CLI arguments is normalized and validated before command construction. For output paths, validation should not only reject `..` components but also ensure the normalized resolved path remains under an intended base directory when the route/component is configured with such a base.