
Documenta a CVE-2026-52618 com um PoC para injeção de comandos no sistema operacional em @webfer/mcp-ansible-drupal via executeDeployment extraVars, além de orientações de detecção e mitigações.
executeDeploymentspawn(cmd[0], cmd.slice(1), { shell: true }) recombina um array de argumentos em uma
única string /bin/sh -c sem escapar, portanto um metacaractere de shell em um
valor de extraVars fornecido à ferramenta MCP executeDeployment é executado no
host que executa o servidor.
| CVE | CVE-2026-52618 |
| CWE | CWE-78 (Neutralização Incorreta de Elementos Especiais usados em um Comando do SO) |
| Pacote | @webfer/mcp-ansible-drupal (npm) |
| Afetado | 2.0.0 |
| Corrigido em | 2.0.3 (publicado em 2026-06-01) |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.4 Alto (transporte stdio). AV:N → 9.8 Crítico se o servidor for encapsulado em um transporte de rede. |
| Reportado por | s1ko (github.com/s1ko, [email protected]) |
| CVE atribuído | 2026-07-13, MITRE CNA-LR |
Este problema está corrigido. Atualize para 2.0.3 ou posterior.
Os argumentos de ferramentas MCP são influenciados pelo atacante. Eles são produzidos por um LLM a partir
do conteúdo que o agente processa — documentos, páginas web, saída de ferramentas —, portanto
a injeção indireta de prompt coloca um atacante no controle dos valores que um manipulador de ferramenta
recebe. Um manipulador que insere qualquer um desses valores em um shell transforma
essa influência em execução de código no host que executa o servidor MCP. Este é
o mesmo modelo do caso precedente aws-mcp-server / CVE-2026-5058.
A consequência é que "o chamador é um LLM confiável" não é uma mitigação. Os argumentos de ferramentas são entrada não confiável.
src/helpers/runAnsible.ts na versão 2.0.0 construía um array de argumentos e então o executava
com o shell habilitado:
const proc = spawn(ansibleCmd[0], ansibleCmd.slice(1), { shell: true });
Com shell: true, o Node não executa ansibleCmd[0] com os elementos restantes como argv. Ele junta todo o array em uma única string e a entrega a /bin/sh -c, sem aplicar aspas ou escape aos elementos. Qualquer elemento que contenha ;, &&, |, crases ou $() portanto escapa do comando pretendido.
O caminho alcançável é a ferramenta MCP executeDeployment (src/tools/executeDeployment.ts), que encaminha os extraVars fornecidos pelo chamador para o array como --extra-vars key=value. Um valor de ; touch /tmp/marker ; resulta em:
/bin/sh -c "ansible-playbook -i inv.ini play.yml ... --extra-vars deploy_env=; touch /tmp/marker ; echo INJECTED"
Um segundo sink na mesma versão interpolava projectRoot em
execSync('ansible-vault encrypt ' + vaultPath).
poc/driver.mjs chama runAnsible diretamente com um valor
extraVars manipulado e verifica a existência do arquivo marcador. O ansible-playbook não
precisa estar instalado — o comando injetado é executado na mesma string /bin/sh -c
independentemente de o binário inicial ser resolvido ou não.
npm pack @webfer/[email protected] && tar xf webfer-mcp-ansible-drupal-2.0.0.tgz
node poc/driver.mjs
Esperado em uma versão afetada:
{"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"}
Validado em 2026-06-01 num contentor isolado e revalidado em 2026-06-13 com
um marcador touch benigno. Execute-o apenas contra infraestruturas que está
autorizado a testar.
--extra-vars que chegue ao ansible-playbook e contenha ;, &&,
||, |, um backtick ou $(. Valores legítimos de variáveis Ansible essencialmente
nunca o fazem.sh -c cuja linha de comando contenha ansible-playbook e um
segundo comando após um separador — um sinal de árvore de processos (auditd, eBPF,
Falco, EDR) que não depende do registo da aplicação.ansible-playbook, git e
ansible-vault são esperados; uma shell, um interpretador ou um cliente de rede não
o são.executeDeployment
contenham metacaracteres de shell. Registe os argumentos das ferramentas — a maioria
das implementações MCP não o faz, e é o único local onde o valor injetado é visível
em termos de aplicação.MITRE ATT&CK T1059.004 Command and Scripting Interpreter: Unix Shell.
Atualize para @webfer/mcp-ansible-drupal 2.0.3 ou posterior. O código-fonte atual
chama spawn(ansibleCmd[0], ansibleCmd.slice(1), { … }) sem a opção shell,
pelo que o array é passado como argv e os metacaracteres perdem o seu significado.
A regra geral para handlers de ferramentas MCP, e o que a correção aplica aqui:
shell: true quando já existe um array de argumentos. A
forma de array existe precisamente para evitar a shell.execFile/spawn com um vetor de argumentos explícito.z.string() do Zod prova que o valor é uma
string e nada sobre o que contém. Use allowlist quando o conjunto de valores é
conhecido; rejeite metacaracteres de shell quando não é.NIST SP 800-53r5 SI-10; OWASP ASVS v4 §5.3.8; mitigações M1 e M2 do CWE-78.
| Data | Evento |
|---|---|
| 2026-06-01 | Vulnerabilidade validada dinamicamente contra a 2.0.0 |
| 2026-06-01 | 2.0.3 publicada no npm com o shell: true removido |
| 2026-06-13 | Revalidada num segundo host |
| 2026-07-13 | MITRE CNA-LR atribui CVE-2026-52618, s1ko creditado como descobridor |
| 2026-08-22 | Publicação deste artigo |
aws-mcp-server)Avisos complementares da mesma ronda de investigação: CVE-2026-52616, CVE-2026-52617.
MIT — consulte LICENSE.