executeDeployment 的额外变量实现操作系统命令注入spawn(cmd[0], cmd.slice(1), { shell: true }) 会重新将参数数组拼接成单个
/bin/sh -c 字符串而不进行转义,因此
提供给 executeDeployment MCP 工具的 extraVars 值中的 shell 元字符会在
运行服务器的宿主机上执行。
| CVE | CVE-2026-52618 |
| CWE | CWE-78(对 OS 命令中使用的特殊元素的不当中和) |
| 软件包 | @webfer/mcp-ansible-drupal (npm) |
| 受影响版本 | 2.0.0 |
| 修复版本 | 2.0.3(2026-06-01 发布) |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 7.8 高危(stdio 传输)。若服务器被包装在网络传输中,AV:N → 9.8 严重。 |
| 上报者 | s1ko (github.com/s1ko, [email protected]) |
| CVE 分配 | 2026-07-13,MITRE CNA-LR |
该问题已修复。请升级到 2.0.3 或更高版本。
MCP 工具参数会受到攻击者影响。它们由 LLM 根据
代理处理的内容(文档、网页、工具输出)生成,因此
间接提示注入使攻击者能够控制工具处理程序收到的值。
任何将这些值中的任意一个送入 shell 的处理程序,都会将该影响转化为
在运行 MCP 服务器的主机上的代码执行。这与
先例 aws-mcp-server / CVE-2026-5058 属于同一模型。
其后果是,“调用方是受信任的 LLM”并非一种缓解措施。 工具参数是不可信输入。
2.0.0 版本中的 src/helpers/runAnsible.ts 构建了一个参数数组,然后
在启用 shell 的情况下运行它:
const proc = spawn(ansibleCmd[0], ansibleCmd.slice(1), { shell: true });
当 shell: true 时,Node 不会以其余元素作为 argv 来执行 ansibleCmd[0]。
它会将整个数组连接成一个字符串并交给
/bin/sh -c,且不对元素进行任何引用或转义。因此,任何带有
;、&&、|、反引号或 $() 的元素都会脱离
预期命令。
可触达路径是 executeDeployment MCP 工具
(src/tools/executeDeployment.ts),它将调用方提供的 extraVars
作为 --extra-vars key=value 转发到数组中。值 ; touch /tmp/marker ;
会产生:
/bin/sh -c "ansible-playbook -i inv.ini play.yml ... --extra-vars deploy_env=; touch /tmp/marker ; echo INJECTED"
同一版本中的另一个 sink 将 projectRoot 插值到
execSync('ansible-vault encrypt ' + vaultPath) 中。
poc/driver.mjs 直接调用 runAnsible,使用构造的
extraVars 值并检查标记文件。无需安装 ansible-playbook——
注入的命令会在同一个 /bin/sh -c 字符串中运行,
无论前导二进制文件是否解析成功。
npm pack @webfer/[email protected] && tar xf webfer-mcp-ansible-drupal-2.0.0.tgz
node poc/driver.mjs
在受影响版本上的预期输出:
{"target":"@webfer/mcp-ansible-drupal 2.0.0","sink":"runAnsible -> spawn(cmd[0], cmd.slice(1), {shell:true})","vector":"executeDeployment extraVars value","marker":"/tmp/PWNED_ansible","created":true,"verdict":"CONFIRMED - command injection executed"}
已于 2026-06-01 在隔离容器中验证,并于 2026-06-13 使用
无害的 touch 标记重新验证。请仅在你获得授权
测试的基础设施上运行。
ansible-playbook 的 --extra-vars 值,若包含 ;、&&、
||、|、反引号或 $(。合法的 Ansible 变量值几乎
不会包含这些字符。sh -c 进程,其命令行包含 ansible-playbook 并且在分隔符后
还有第二条命令——这是一种进程树信号(auditd、eBPF、
Falco、EDR),不依赖应用程序日志。ansible-playbook、git 和
ansible-vault 是预期的;shell、解释器或网络客户端
则不是。executeDeployment 参数包含 shell
元字符。记录工具参数——大多数 MCP 部署不会记录,而这是
在应用程序层面唯一能看到注入值的位置。MITRE ATT&CK T1059.004 命令和脚本解释器:Unix Shell。
请升级到 @webfer/mcp-ansible-drupal 2.0.3 或更高版本。 当前源码
调用 spawn(ansibleCmd[0], ansibleCmd.slice(1), { … }) 时没有 shell 选项,
因此数组会作为 argv 传递,元字符将失去其特殊含义。
MCP 工具处理程序的通用规则,以及本修复在此处所应用的原则:
shell: true。
数组形式正是为了避免 shell 而存在的。execFile/spawn 并显式传入参数向量。z.string() 只能证明该值是字符串,
并不能说明其中包含什么。在值集合已知时使用白名单;
在未知时拒绝 shell 元字符。NIST SP 800-53r5 SI-10; OWASP ASVS v4 §5.3.8; CWE-78 的缓解措施 M1 和 M2。
| 日期 | 事件 |
|---|---|
| 2026-06-01 | 对 2.0.0 进行了动态漏洞验证 |
| 2026-06-01 |
aws-mcp-server)同一研究过程中的配套公告: CVE-2026-52616, CVE-2026-52617.
MIT — 参见 LICENSE。
2.0.3 发布到 npm,移除了 shell: true |
| 2026-06-13 | 在第二台主机上重新验证 |
| 2026-07-13 | MITRE CNA-LR 分配 CVE-2026-52618,s1ko 被记为发现者 |
| 2026-08-22 | 本文发布 |