
Documente la CVE-2026-52618 avec un PoC pour une injection de commandes système dans @webfer/mcp-ansible-drupal via executeDeployment extraVars, plus des conseils de détection et des mesures d'atténuation.
executeDeploymentspawn(cmd[0], cmd.slice(1), { shell: true }) réassemble un tableau d'arguments en une
seule chaîne /bin/sh -c sans échappement, de sorte qu'un métacaractère de shell dans une
valeur extraVars fournie à l'outil MCP executeDeployment s'exécute sur l'hôte
exécutant le serveur.
| CVE | CVE-2026-52618 |
| CWE | CWE-78 (Neutralisation incorrecte des éléments spéciaux utilisés dans une commande OS) |
| Paquet | @webfer/mcp-ansible-drupal (npm) |
| Affecté | 2.0.0 |
| Corrigé dans | 2.0.3 (publié le 2026-06-01) |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.4 Élevé (transport stdio). AV:N → 9.8 Critique si le serveur est encapsulé dans un transport réseau. |
| Signalé par | s1ko (github.com/s1ko, [email protected]) |
| CVE attribué | 2026-07-13, MITRE CNA-LR |
Ce problème est corrigé. Mettez à niveau vers 2.0.3 ou une version ultérieure.
Les arguments des outils MCP sont influencés par l'attaquant. Ils sont produits par un LLM à partir
du contenu que l'agent traite — documents, pages web, sortie d'outils — de sorte qu'une
injection de prompt indirecte place un attaquant aux commandes des valeurs que reçoit un gestionnaire
d'outil. Un gestionnaire qui transmet l'une de ces valeurs à un shell transforme
cette influence en exécution de code sur l'hôte exécutant le serveur MCP. C'est
le même modèle que le cas précédent aws-mcp-server / CVE-2026-5058.
La conséquence est que « l'appelant est un LLM de confiance » ne constitue pas une atténuation. Les arguments des outils sont des entrées non fiables.
src/helpers/runAnsible.ts dans la version 2.0.0 construisait un tableau d'arguments puis l'exécutait
avec le shell activé :
const proc = spawn(ansibleCmd[0], ansibleCmd.slice(1), { shell: true });
Avec shell: true, Node n'exécute pas ansibleCmd[0] avec les éléments restants comme argv. Il joint l'ensemble du tableau en une seule chaîne et la transmet à /bin/sh -c, sans appliquer de quoting ni d'échappement aux éléments. Tout élément contenant ;, &&, |, des backticks ou $() s'échappe donc de la commande prévue.
Le chemin accessible est l'outil MCP executeDeployment (src/tools/executeDeployment.ts), qui transmet les extraVars fournies par l'appelant dans le tableau sous la forme --extra-vars key=value. Une valeur de ; touch /tmp/marker ; produit :
/bin/sh -c "ansible-playbook -i inv.ini play.yml ... --extra-vars deploy_env=; touch /tmp/marker ; echo INJECTED"
Un second point d'injection dans la même version interpolait projectRoot dans
execSync('ansible-vault encrypt ' + vaultPath).
poc/driver.mjs appelle directement runAnsible avec une valeur
extraVars forgée et vérifie la présence du fichier marqueur. ansible-playbook n'a pas
besoin d'être installé — la commande injectée s'exécute dans la même chaîne /bin/sh -c
que le binaire de tête soit résolu ou non.
npm pack @webfer/[email protected] && tar xf webfer-mcp-ansible-drupal-2.0.0.tgz
node poc/driver.mjs
Attendu sur une version affectée :
{"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"}
Validé le 2026-06-01 dans un conteneur isolé et revalidé le 2026-06-13 avec
un marqueur touch bénin. Ne l'exécutez que contre une infrastructure que vous êtes autorisé
à tester.
--extra-vars atteignant ansible-playbook qui contient ;, &&,
||, |, un backtick ou $(. Les valeurs de variables Ansible légitimes n'en
contiennent essentiellement jamais.sh -c dont la ligne de commande contient ansible-playbook et une
seconde commande après un séparateur — un signal d'arborescence de processus (auditd, eBPF,
Falco, EDR) qui ne dépend pas de la journalisation applicative.ansible-playbook, git et
ansible-vault sont attendus ; un shell, un interpréteur ou un client réseau ne le sont pas.executeDeployment contiennent des
métacaractères de shell. Journalisez les arguments des outils — la plupart des déploiements MCP
ne le font pas, et c'est le seul endroit où la valeur injectée est visible en termes applicatifs.MITRE ATT&CK T1059.004 Command and Scripting Interpreter: Unix Shell.
Mettez à niveau vers @webfer/mcp-ansible-drupal 2.0.3 ou une version ultérieure. Le code source actuel
appelle spawn(ansibleCmd[0], ansibleCmd.slice(1), { … }) sans option shell,
de sorte que le tableau est passé comme argv et les métacaractères perdent leur sens.
La règle générale pour les gestionnaires d'outils MCP, et ce que le correctif applique ici :
shell: true lorsqu'un tableau d'arguments est déjà disponible. La
forme en tableau existe précisément pour éviter le shell.execFile/spawn avec un vecteur d'arguments explicite.z.string() de Zod prouve que la valeur est une
chaîne et rien sur ce qu'elle contient. Utilisez une liste d'autorisation lorsque l'ensemble des valeurs est
connu ; rejetez les métacaractères de shell lorsqu'il ne l'est pas.NIST SP 800-53r5 SI-10 ; OWASP ASVS v4 §5.3.8 ; atténuations CWE-78 M1 et M2.
| Date | Événement |
|---|---|
| 2026-06-01 | Vulnérabilité validée dynamiquement contre 2.0.0 |
| 2026-06-01 | 2.0.3 publiée sur npm avec le shell: true supprimé |
| 2026-06-13 | Revalidée sur un second hôte |
| 2026-07-13 | MITRE CNA-LR attribue CVE-2026-52618, s1ko crédité comme découvreur |
| 2026-08-22 | Publication de cet article |
aws-mcp-server)Avis complémentaires issus de la même passe de recherche : CVE-2026-52616, CVE-2026-52617.
MIT — voir LICENSE.