oscerd/CVE-2026-40047
GitHub: oscerd/CVE-2026-40047
Apache Camel camel-docling 组件 CLI 参数注入与路径穿越漏洞(CVE-2026-40047)的概念验证与复现工具。
Stars: 2 | Forks: 0
# camel-docling CLI Argument Injection / Path Traversal 复现器 (CVE-2026-40047)
本项目演示了 Apache
Camel 的 `camel-docling` 组件中的一个 **CLI argument injection 和 path traversal** 漏洞,追踪编号为 **CVE-2026-40047**。`DoclingProducer` 根据
message header 构建对外部 `docling` 命令行工具的调用;通过 `CamelDoclingCustomArguments` header 传入的 custom arguments 在被追加时缺乏充分的验证(仅使用 denylist
和字面量 `../` 检查),因此能够影响这些 header 的攻击者可以向子进程注入任意的 `docling`
CLI flag 和包含 traversal 的 path 值。
Advisory: https://camel.apache.org/security/CVE-2026-40047.html
## 漏洞概述
| Property | Value |
|----------|-------|
| **Component** | `camel-docling` |
| **Affected Class** | `org.apache.camel.component.docling.DoclingProducer` (`addCustomArguments` / `validateCustomArguments`) |
| **Root cause** | `CamelDoclingCustomArguments` (一个 `List`) 被追加到 `docling` CLI args 时,仅使用了较弱的 denylist + 字面量 `../` 检查 |
| **CWE** | CWE-88 (Argument Injection) / CWE-22 (Path Traversal) |
| **Impact** | 向外部工具注入任意/非预期的 `docling` CLI flag 和目录外的 path 值。这不是 OS command injection(基于 list 的 ProcessBuilder,没有 shell)。 |
| **Affected Versions** | 从 4.15.0 到 4.18.3 之前的版本 |
| **Fixed Versions** | 4.18.3, 4.19.0 |
| **JIRA** | CAMEL-23212 |
| **Reporter** | Andrea Cosentino (Apache Software Foundation) |
## 技术细节
`DoclingProducer` 组装 `docling` 调用并通过 `java.lang.ProcessBuilder`(list
形式——无 shell)运行它。来自 `CamelDoclingCustomArguments` header 的 custom CLI arguments 会被追加到
命令中:
```
// 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);
}
```
在受影响的版本中,`validateCustomArguments` 依赖于一个不允许 flag 的 **denylist**,并且只
拒绝包含字面量 `../` 的 path 值。因此:
- **无法识别的 flag**(不在 denylist 中)被直接传递给 `docling`。
- **类似 path 的值**,如果不包含字面量 `../`(绝对路径或规范化序列)就不会被拦截。
因为 Camel 构建了 `docling` 的调用,所以该组件负责约束这些
值。修复方案 (CAMEL-23212) 将 denylist 替换为已识别 flag 的严格 **allowlist**,
拒绝 producer 管理的 flag(`--output`/`-o`)和 shell 元字符(纵深防御),并在验证前使用 `Path.normalize()` 规范化类似 path 的值。
## 路由
```
from("direct:convert")
.to("docling:convert?operation=CONVERT_TO_MARKDOWN&contentInBody=true");
```
## 本复现程序如何观察注入
`docling` 是一个外部工具。本复现程序附带了一个 **stub `docling`**(位于容器内的
`PATH` 中),它会记录接收到的 argv 并写回一个 markdown 文件,因此被注入的参数
将在 HTTP 响应和 `/tmp/docling-invocations.log` 中可见。所有这些都运行在一个 Docker
镜像中(app + stub)——因此不需要安装真正的 `docling`。
## 前置条件
- Java 17+ 和 Maven 3.8+(用于构建 jar)
- Docker(运行 app + stub `docling`)
## 复现步骤
### 步骤 1:构建 jar 和镜像
```
mvn clean package -DskipTests
docker compose up -d --build
```
### 步骤 2:良性转换
```
curl http://localhost:8080/exploit/normal
# stub docling 接收:docling --to md --ocr-lang en --output /tmp/input.txt
```
### 步骤 3:注入任意 CLI arguments
```
curl "http://localhost:8080/exploit/attack"
# 注入 CamelDoclingCustomArguments = [--injected-by-attacker, arbitrary-value]
# -> stub docling 接收:
# docling --injected-by-attacker arbitrary-value --to md --ocr-lang en --output /tmp/input.txt
# 不包含字面量 "../" 的 path 值(绝对路径)同样可以通过:
curl "http://localhost:8080/exploit/attack?flag=--artifacts-path&value=/etc/attacker-controlled"
```
在受影响的版本上(本复现程序锁定为 **4.18.2**),路由会**成功**执行,并且被注入的
参数会到达子进程。在已修复的版本(4.18.3 / 4.19.0)上,allowlist 会以
`IllegalArgumentException` 拒绝 `--injected-by-attacker`,从而导致路由失败。
### 清理
```
docker compose down
```
## 漏洞利用条件
1. 一个 Camel 路由将受外部影响的数据转发到 `docling:` producer 的 `CamelDoclingCustomArguments`(或
包含路径的 header)中。
2. 没有对来自不受信任的 producer 的 message 剥离 Camel 内部的 header。
## 推荐修复
升级到 4.18.3 / 4.19.0。该修复使用已识别 `docling` flag 的严格 allowlist,拒绝
producer 管理的 flag 和 shell 元字符,并在验证它们
之前使用 `Path.normalize()` 规范化 path 值。
## 缓解措施
在升级之前:
1. **不要将不受信任的内容**映射到 `CamelDoclingCustomArguments` 或包含路径的 header 中。
2. **剥离 Camel 内部的 header**(`removeHeaders("Camel*")`),针对来自不受信任的
producer 的 message,在到达 `docling:` producer 之前进行处理。
## 文件
```
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
```
## 免责声明
本复现程序仅供**安全研究和授权测试使用**,针对的是一个**已公开
披露且已修复**的漏洞。未经明确许可,请勿将其用于任何系统。
标签:Apache Camel, JS文件枚举, Maven, 参数注入, 域名枚举, 漏洞复现, 漏洞验证, 版权保护, 请求拦截, 路径穿越