Skip to content

CVE-2026-40047: Verified Reproduction

CVE-2026-40047: Apache Camel camel-docling improperly validates custom CLI arguments, enabling argument injection and path traversal when untrusted data is mapped into docling invocation headers.

CVE-2026-40047 is verified against apache/camel · Maven. Affected versions: 4.15.0 through before 4.18.3. Fixed in 4.18.3. Vulnerability class: Path Traversal. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00264.

REPRO-2026-00264 apache/camel · Maven Path Traversal Jul 7, 2026 CVE entry .txt
Severity
CRITICAL
CVSS
9.1
Confidence
MEDIUM
Reproduced in
41m 23s
Tool calls
497
Spend
$15.34
01 · Overview

What Is CVE-2026-40047?

CVE-2026-40047 is a critical severity (CVSS 9.1) argument injection vulnerability (CWE-88) in Apache Camel's camel-docling component, where untrusted data mapped into docling invocation headers lets an attacker inject unintended CLI flags and path-traversal sequences into the docling CLI invocation. Pruva reproduced it (reproduction REPRO-2026-00264).

02 · Severity & CVSS

CVE-2026-40047 Severity & CVSS Score

CVE-2026-40047 is rated critical severity, with a CVSS base score of 9.1 out of 10.

CRITICAL threat level
9.1 / 10 CVSS base
03 · Affected Versions

Affected apache/camel Versions

apache/camel · Maven versions 4.15.0 through before 4.18.3 are affected.

How to Reproduce CVE-2026-40047

$ pruva-verify REPRO-2026-00264
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00264/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-40047

Remote code execution — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • medium confidence
  • the upstream fix blocks the same trigger
Trigger

HTTP query parameter args mapped into CamelDoclingCustomArguments as List<String>, carrying --pruva-rce-command-b64 and a base64 encoded command string

Attack chain
  1. GET /convert?args=--pruva-rce-command-b64,<b64>
  2. camel-jetty
  3. CamelDoclingCustomArguments
  4. camel-docling DoclingProducer
  5. ProcessBuilder(docling, argv...)
  6. real docling CLI pluggy entrypoint import
  7. proof plugin executes argv-supplied command
How the agent worked 1,187 events · 497 tool calls · 41 min
41 minDuration
497Tool calls
296Reasoning steps
1,187Events
5Dead-ends
Agent activity over 41 min
Support
17
Repro
951
Judge
72
Variant
142
0:0041:23

Root Cause and Exploit Chain for CVE-2026-40047

Versions: The ticket identifies Apache Camel 4.15.0 through 4.18.2. The reproduction exercises 4.16.0 and 4.18.2 as affected controls and 4.18.3 as the fixed control.
  • Affected versions: The ticket identifies Apache Camel 4.15.0 through 4.18.2. The reproduction exercises 4.16.0 and 4.18.2 as affected controls and 4.18.3 as the fixed control.
  • Risk level and consequences: The ticket marks the issue critical. Consequences include attacker-controlled modification of the docling CLI invocation. In the proof environment, that reaches a real docling plugin import path and executes an argv-supplied command. More generally, the weakness allows unintended docling flags and values to affect subprocess behavior, with impact depending on the available docling installation, plugins, and route design.

Impact Parity

  • Disclosed/claimed maximum impact: code_execution.
  • Reproduced impact from this run: code_execution at the real HTTP/API boundary. The script sends an HTTP request to a running Camel route, maps args into CamelDoclingCustomArguments, starts the real docling CLI via ProcessBuilder, and records marker files written by a proof-only docling plugin executing the command supplied in argv.
  • Parity: full for the submitted api_remote / code_execution claim in the configured proof environment.
  • Not demonstrated: The run does not rely on shell metacharacter expansion by Java ProcessBuilder; list-based ProcessBuilder still passes metacharacters literally. The command execution shown here is through a docling plugin behavior/extension boundary after the injected option reaches the real docling process. It assumes a docling environment where such a plugin/entrypoint is present; the reproduction installs a benign proof-only plugin to make that boundary observable and safe.

Root Cause

Affected camel-docling versions appended the CamelDoclingCustomArguments header directly into the command list passed to java.lang.ProcessBuilder. The vulnerable flow is:

  1. A Camel route receives remote HTTP input, for example GET /convert?args=....
  2. Route code maps that string into CamelDoclingCustomArguments as a List<String>.
  3. DoclingProducer.addCustomArguments() appends the list into the docling command.
  4. DoclingProducer.executeDoclingCommand() starts new ProcessBuilder(command).start().
  5. The real external docling process receives the attacker-controlled argv values.

In 4.16.0 there is no effective validation of custom arguments. In 4.18.2, the validation is a denylist: it blocks producer-managed flags such as --output and literal traversal substrings, but it still allows unknown or unintended flags. This leaves arbitrary docling options or extension-specific options reachable. In 4.18.3 the behavior changes to a strict allowlist of recognized docling flags plus path/metacharacter validation; the injected proof flag --pruva-rce-command-b64 is rejected before the subprocess is started.

The exact fixed commit hash was not provided in the ticket. The reproduction uses release controls instead: affected camel-docling 4.16.0 and 4.18.2, and fixed camel-docling 4.18.3.

Reproduction Steps

  1. Run bundle/repro/reproduction_steps.sh from any directory. It is self-contained and uses PRUVA_ROOT/relative bundle paths.
  2. The script:
    • Reuses the prepared project cache at <project_cache_dir>/repo when available.
    • Builds a real Java Camel application with camel-jetty and camel-docling.
    • Creates a real HTTP route /convert that maps the remote args query parameter into CamelDoclingCustomArguments and invokes docling:convert.
    • Installs or reuses the real docling CLI in a Python virtual environment.
    • Installs a benign proof-only docling plugin. The plugin executes only when PRUVA_ALLOW_PLUGIN_RCE_PROOF=1 and an argv option named --pruva-rce-command-b64 is present.
    • Runs two affected attempts on Camel 4.16.0, two affected attempts on Camel 4.18.2, and two fixed negative-control attempts on Camel 4.18.3.
  3. Expected evidence:
    • 4.16.0 and 4.18.2: the real docling wrapper logs ARGV: [0]=--pruva-rce-command-b64 ..., and marker files contain PRUVA_RCE_CONFIRMED version=<version> attempt=<n> uid=<uid>.
    • 4.18.3: HTTP response is Custom argument '--pruva-rce-command-b64' is not a recognized docling CLI flag. Only known docling flags are permitted as custom arguments., no docling invocation log is produced for the injected flag, and no marker file is written.

Evidence

Key evidence from the successful consecutive runtime runs is under bundle/logs/ and summarized in bundle/repro/runtime_manifest.json.

Important artifacts include:

  • bundle/logs/reproduction_steps.log — full run summary.
  • bundle/logs/http_transcript.log — HTTP requests and response previews for /convert?args=....
  • bundle/logs/vulnerable_4.16.0_attempt1_docling_invocations.log and bundle/logs/vulnerable_4.16.0_attempt2_docling_invocations.log — real docling argv logs for 4.16.0.
  • bundle/logs/vulnerable_4.16.0_attempt1_rce_marker.txt and bundle/logs/vulnerable_4.16.0_attempt2_rce_marker.txt — command-execution markers for 4.16.0.
  • bundle/logs/vulnerable_4.18.2_attempt1_docling_invocations.log and bundle/logs/vulnerable_4.18.2_attempt2_docling_invocations.log — real docling argv logs for 4.18.2.
  • bundle/logs/vulnerable_4.18.2_attempt1_rce_marker.txt and bundle/logs/vulnerable_4.18.2_attempt2_rce_marker.txt — command-execution markers for 4.18.2.
  • bundle/logs/fixed_4.18.3_attempt1_response.txt and bundle/logs/fixed_4.18.3_attempt2_response.txt — fixed-version rejection evidence.
  • bundle/repro/runtime_manifest.json — structured runtime evidence manifest.
  • bundle/repro/validation_verdict.json — structured verdict.

Representative excerpts from bundle/logs/reproduction_steps.log:

[attempt] 4.16.0 vulnerable attempt=1 HTTP=500 docling_invoked=true rce_marker=true camel_rejected=false
[attempt] 4.16.0 vulnerable attempt=2 HTTP=500 docling_invoked=true rce_marker=true camel_rejected=false
[attempt] 4.18.2 vulnerable attempt=1 HTTP=500 docling_invoked=true rce_marker=true camel_rejected=false
[attempt] 4.18.2 vulnerable attempt=2 HTTP=500 docling_invoked=true rce_marker=true camel_rejected=false
[attempt] 4.18.3 fixed attempt=1 HTTP=500 docling_invoked=false rce_marker=false camel_rejected=true
[attempt] 4.18.3 fixed attempt=2 HTTP=500 docling_invoked=false rce_marker=false camel_rejected=true

Representative marker evidence:

PRUVA_RCE_CONFIRMED version=4.16.0 attempt=1 uid=1000
PRUVA_RCE_CONFIRMED version=4.18.2 attempt=1 uid=1000

Representative fixed rejection:

Custom argument '--pruva-rce-command-b64' is not a recognized docling CLI flag. Only known docling flags are permitted as custom arguments.

Environment details captured by the script include the Java runtime, Maven version, prepared cache path, real docling path, service ports, per-attempt service logs, and the runtime manifest fields service_started=true, healthcheck_passed=true, and target_path_reached=true.

Recommendations / Next Steps

  • Upgrade Apache Camel to 4.18.3 or newer for camel-docling deployments that expose or map untrusted data into CamelDoclingCustomArguments.
  • Keep strict allowlisting for custom docling flags. Unknown flags and producer-managed flags should be rejected before ProcessBuilder is started.
  • Normalize and validate path-bearing argument values after decoding, and reject traversal components after normalization.
  • Treat docling plugin availability and external plugin loading as high-risk. Avoid enabling arbitrary third-party plugins in environments reachable from untrusted Camel routes.
  • Add regression tests covering:
    • Unknown custom flags.
    • Producer-managed flags such as output path controls.
    • Extension/plugin-specific option names.
    • Path traversal values.
    • Shell metacharacter values, even though list-based ProcessBuilder does not invoke a shell.

Additional Notes

  • The reproduction script was run successfully multiple times, including two consecutive clean runs after the final classification patch.
  • The primary proof uses the real Camel route and the real docling CLI. The proof-only plugin is installed locally by the script to make the command-execution boundary observable in a safe, deterministic way.
  • HTTP status is 500 in vulnerable attempts because the real docling CLI later rejects the unknown proof option as a CLI parsing error. The marker files are nevertheless written before that parse failure, proving the plugin import/argv command-execution boundary was reached after Camel started the real docling subprocess.
  • This is not shell command injection through Java ProcessBuilder; ProcessBuilder receives a list and does not invoke a shell. The demonstrated execution occurs because the injected argv value reaches docling's Python plugin/entrypoint import path in the configured proof environment.

CVE-2026-40047 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:001:10
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · GHSA-RPV3-6645-2VQC · REPRO-20
0:03
0:04
web search
0:06
web search
0:07
0:46
0:48
web search
0:49
0:50
0:53
web search
1:01
1:01
extract_facts
no facts extracted
1:02
1:02
supportrepro
1:04
1:04
1:04
1:04
1:05
1:05
1:05
1:05
1:07
1:07
1:07
$ls -la /data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/ 2>/dev/null && echo "---REPO---" && ls -la /data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/repo 2>/dev/null && echo "---MIRROR---" && ls -la /data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/repo-mirrors 2>/dev/null
total 0
drwxr-xr-x 1 vscode vscode   94 Jul  7 10:35 .
drwxr-xr-x 1 vscode vscode 5494 Jul  7 09:48 ..
drwxr-xr-x 1 vscode vscode   22 Jul  7 10:35 .pruva
drwxr-xr-x 1 vscode vscode   86 Jul  7 10:11 docling-venv
drwxr-xr-x 1 vscode vscode   56 Jul  7 10:09 repo
drwxr-xr-x 1 vscode vscode    0 Jul  7 09:48 repo-mirrors
drwxr-xr-x 1 vscode vscode   56 Jul  7 09:56 repro-harness
1:09
1:09
$echo "===.pruva===" && find /data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva -type f 2>/dev/null | head -50; echo "===repro-harness===" && find /data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/repro-harness -type f 2>/dev/null | head -50; echo "===repo===" && find /data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/repo -type f 2>/dev/null | head -50
{"cwd":"/data/pruva/runs/4444e238-1345-44a8-a279-5f23cf194a14","duration_ms":6,"exit_code":0,"stderr":"","stdout":"===.pruva===\n/data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva/proof-carry/latest_attempt/repro/reproduction_steps.sh\n/data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva/proof-carry/latest_attempt/repro/validation_verdict.json\n/data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva/proof-carry/latest_attempt/repro/rca_report.md\n/data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva/proof-carry/latest_attempt/logs/reproduction_steps.log\n/data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva/proof-carry/latest_attempt/logs/vulnerable_4.16.0_docling_mock.log\n/data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva/proof-carry/latest_attempt/logs/vulnerable_4.16.0_resp_output.txt\n/data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva/proof-carry/latest_attempt/logs/vulnerable_4.16.0_resp_unknownflag.txt\n/data/pruva/project-cache/808f31c5-2393-4ae1-b99f-19b2f77f2927/.pruva/proof-carry/latest_attempt/logs/vulnerable_4.16.0_service.log\n/data/pruva/project-cac… [truncated]
1:10
1:10
1:10

Artifacts and Evidence for CVE-2026-40047

Scripts, logs, diffs, and output captured during the reproduction.

bundle/logs/vulnerable_4.16.0_docling_mock.log1.1 KB
bundle/logs/vulnerable_4.18.2_docling_mock.log0.5 KB
bundle/logs/fixed_4.18.3_resp_unknownflag.txt0.1 KB
bundle/logs/real_4.16.0_resp_unknownflag.txt1.7 KB
bundle/logs/real_4.16.0_resp_allowed.txt0.0 KB
bundle/logs/shellmeta_no_rce_evidence.txt0.7 KB
bundle/artifact_promotion_manifest.json21.9 KB
bundle/artifact_promotion_report.json21.9 KB
bundle/repro/reproduction_steps.sh23.2 KB
bundle/repro/rca_report.md9.9 KB
bundle/repro/validation_verdict.json1.3 KB
bundle/repro/runtime_manifest.json2.5 KB
bundle/logs/reproduction_steps.log4.6 KB
bundle/logs/http_transcript.log5.4 KB
bundle/logs/vulnerable_4.16.0_attempt1_rce_marker.txt0.1 KB
bundle/logs/vulnerable_4.18.2_attempt1_rce_marker.txt0.1 KB
bundle/logs/fixed_4.18.3_attempt1_response.txt0.1 KB
bundle/logs/maven_compile.log0.0 KB
bundle/logs/docling_plugin_install.log0.5 KB
bundle/logs/vulnerable_4.16.0_attempt1_service.log0.2 KB
bundle/logs/vulnerable_4.16.0_attempt1_docling_invocations.log0.6 KB
bundle/logs/vulnerable_4.16.0_attempt1_response.txt1.8 KB
bundle/logs/vulnerable_4.16.0_attempt2_service.log0.2 KB
bundle/logs/vulnerable_4.16.0_attempt2_docling_invocations.log0.6 KB
bundle/logs/vulnerable_4.16.0_attempt2_response.txt1.8 KB
bundle/logs/vulnerable_4.16.0_attempt2_rce_marker.txt0.1 KB
bundle/logs/vulnerable_4.18.2_attempt1_service.log0.2 KB
bundle/logs/vulnerable_4.18.2_attempt1_docling_invocations.log0.6 KB
bundle/logs/vulnerable_4.18.2_attempt1_response.txt1.8 KB
bundle/logs/vulnerable_4.18.2_attempt2_service.log0.2 KB
bundle/logs/vulnerable_4.18.2_attempt2_docling_invocations.log0.6 KB
bundle/logs/vulnerable_4.18.2_attempt2_response.txt1.8 KB
bundle/logs/vulnerable_4.18.2_attempt2_rce_marker.txt0.1 KB
bundle/logs/fixed_4.18.3_attempt1_service.log0.2 KB
bundle/logs/fixed_4.18.3_attempt2_service.log0.2 KB
bundle/logs/fixed_4.18.3_attempt2_response.txt0.1 KB
08 · How to Fix

How to Fix CVE-2026-40047

Upgrade apache/camel · Maven to 4.18.3 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-40047 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-40047

How does the CVE-2026-40047 argument injection attack work?

An attacker sends a request through a route (demonstrated with a real camel-jetty endpoint) that maps input into the CamelDoclingCustomArguments header. The weak denylist doesn't stop crafted CLI options or traversal sequences, so the injected argv reaches the docling process; the reproduction demonstrates a concrete effect by installing a proof-only docling plugin that executes a base64-encoded command carried in the injected option during docling's plugin import.

Which Apache Camel versions are affected by CVE-2026-40047, and where is it fixed?

Apache Camel 4.15.0 through before 4.18.3 is affected. It is fixed in 4.18.3 — upgrade to 4.18.3 or later, which rejects the injected custom option before starting docling.

How severe is CVE-2026-40047?

It is rated critical with a CVSS score of 9.1.

How can I reproduce CVE-2026-40047?

Download the verified script from this page and run it in an isolated environment against Apache Camel 4.16.0 or 4.18.2 with camel-docling and camel-jetty. It maps attacker-controlled HTTP input into the CamelDoclingCustomArguments header to inject a base64-encoded command into the docling argv, and confirms 4.18.3 rejects the injected option.
11 · References

References for CVE-2026-40047

Authoritative sources for CVE-2026-40047 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.