
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 }) rejoint un tableau d'arguments en une
seule chaîne /bin/sh -c sans échappement ; ainsi, un métacaractère de shell dans une
valeur extraVars fournie à l'outil MCP executeDeployment s'exécute sur
l'hôte qui exécute le serveur.
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, sorties d'outils — de sorte
qu'une injection indirecte par prompts donne à l'attaquant le contrôle des valeurs que le
gestionnaire d'outil reçoit. Un gestionnaire qui transmet l'une de ces valeurs à un shell transforme
cette influence en exécution de code sur l'hôte qui exécute 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 » n'est pas une mesure d'atténuation. Les arguments d'outils sont des entrées non fiables.
Dans la version 2.0.0, src/helpers/runAnsible.ts 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 tout le tableau en une seule chaîne et la transmet à
/bin/sh -c, sans guillemets ni échappement appliqués aux éléments. Tout élément
contenant ;, &&, |, des backticks ou $() s'échappe donc de la commande
prévue.
La voie d'accès 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 sink de la même version interpolait projectRoot dans
execSync('ansible-vault encrypt ' + vaultPath).
poc/driver.mjs appelle runAnsible directement avec une valeur
extraVars conçue 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 en tête se résolve ou non.
npm pack @webfer/[email protected] && tar xf webfer-mcp-ansible-drupal-2.0.0.tgz
node poc/driver.mjs
Résultat 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 re-validé 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 légitimes de variables Ansible ne le font pratiquement
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 sont pas
attendus.executeDeployment contiennent des
métacaractères de shell. Journalisez les arguments d'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 que 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 tableau existe précisément pour éviter le shell.execFile/spawn avec un vecteur d'arguments explicite.z.string() Zod prouve que la valeur est une
chaîne, mais rien sur son contenu. Utilisez une liste blanche lorsque l'ensemble des valeurs est
connu ; rejetez les métacaractères de shell quand il ne l'est pas.NIST SP 800-53r5 SI-10 ; OWASP ASVS v4 §5.3.8 ; CWE-78 mitigations M1 et M2.
aws-mcp-server)Avis associés issus de la même campagne de recherche : CVE-2026-52616, CVE-2026-52617.
MIT — voir LICENSE.
| CVE | CVE-2026-52618 |
| CWE | CWE-78 (Improper Neutralization of Special Elements used in an OS Command) |
| 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 = 7.8 É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 assigné | 2026-07-13, MITRE CNA-LR |
| Date |
|---|
| Événement |
|---|
| 2026-06-01 | Vulnérabilité validée dynamiquement sur la version 2.0.0 |
| 2026-06-01 | 2.0.3 publié sur npm avec le shell: true supprimé |
| 2026-06-13 | Re-validé sur un second hôte |
| 2026-07-13 | MITRE CNA-LR assigne CVE-2026-52618, s1ko crédité comme découvreur |
| 2026-08-22 | Publication de cet article |