~4 minutes
L’injection de commandes, ça date de l’ère Unix. Mais dans le contexte MCP, c’est pire : le modèle IA est l’interpréteur. Et lui, il ne doute jamais de ce qu’il construit.
Partie de la série OWASP MCP Top 10
Description du risque
L’injection de commandes dans le contexte MCP est une version amplifiée du problème classique car ici, le modèle IA est l’interpréteur.
La Command Injection dans le contexte MCP se produit quand un agent IA construit et exécute des commandes système en utilisant des entrées non fiables sans validation appropriée. C’est analogue aux injections classiques (SQL, shell), mais avec une différence clé : le modèle IA est l’interpréteur, et le texte en langage naturel est le payload.
L’agent ne distingue pas “instruction de travail” et “commande malveillante” , caril fait confiance à tout ce qui arrive dans son contexte. C’est shell=True appliqué à l’IA.
Vecteurs d’attaque
On distingue quatre vecteurs principaux d’injection de commandes dans les outils MCP :
1. Injection directe via le prompt utilisateur
L’attaquant fournit un prompt contenant des métacaractères shell (;, &&, |, backticks, $(...)). L’agent les passe au système sans validation.
2. Injection indirecte via contenu de fichier
L’agent lit un fichier dont le contenu contient des instructions déguisées en commandes à exécuter.
3. Injection via arguments de commande
Manipulation des arguments : path traversal (../../etc/passwd), options (--help; cat /etc/shadow).
4. Exploitation de shell=True
Le vecteur le plus critique en Python : subprocess.run(cmd, shell=True) active toute l’interpolation shell.
Analyse STRIDE
| Catégorie STRIDE | Applicable | Explication |
|---|---|---|
| Spoofing (Usurpation d’identité) | Modéré | Les commandes injectées se font passer pour des opérations légitimes. |
| Tampering (Falsification) | Oui | L’exécution de commandes permet de modifier des fichiers système et des configurations. |
| Repudiation (Répudiation) | Oui | Les commandes sont attribuées au processus MCP, pas à l’attaquant. |
| Information Disclosure (Divulgation d’informations) | Oui | cat /etc/shadow, env — un simple curl suffit à exfiltrer. |
| Denial of Service (Déni de service) | Oui | rm -rf /, fork bombs, kill -9 -1 — des commandes destructrices triviales. |
| Elevation of Privilege (Élévation de privilèges) | Oui (PRIMAIRE) | L’injection de commandes = exécution de code avec les privilèges du serveur MCP. Si le processus tourne en root, c’est un accès total. |
Impact potentiel
| Impact | Niveau | Description de l'impact |
|---|---|---|
| Confidentialité | Critique | L'attaquant lit tous les fichiers accessibles : clés privées, tokens, données utilisateur. Exfiltration en une commande. |
| Intégrité | Critique | Modification de fichiers, installation de backdoors, altération de logs pour couvrir ses traces. |
| Disponibilité | Élevé | Commandes destructrices, saturation des ressources, arrêt de services. |
| Réputation | Élevé | Un serveur MCP compromis utilisé pour attaquer d'autres cibles impacte directement l'organisation. |
Recommandations de mitigation
Je constate que la majorité des injections de commandes dans les outils MCP sont évitables avec quelques réflexes fondamentaux. Voici les cinq règles que a appliquer systématiquement.
1. Bannir shell=True
shell=True est la source de presque tous les problèmes. Il active l’interpolation shell complète : métacaractères, substitution de variables, pipes. La règle est simple : on passe toujours une liste d’arguments, jamais une chaîne construite dynamiquement.
2. Whitelist stricte des commandes autorisées
Plutôt que de blacklister les commandes dangereuses (une bataille perdue d’avance), définir une liste fermée de ce qui est autorisé. Tout ce qui n’est pas dans la liste est rejeté avant même d’atteindre le système.
Une whitelist de 10 commandes est plus sûre qu’une blacklist de 10 000 patterns.
3. Valider et assainir les arguments avec shlex
Même avec shell=False, un argument malformé peut provoquer des comportements inattendus (path traversal, null bytes). Utilisershlex.split() pour parser les arguments, et vérifier l’absence de .. dans les chemins par exemple.
import shlex, os
def sanitize_path(path: str) -> str:
clean = os.path.normpath(path)
if ".." in clean.split(os.sep):
raise ValueError("Path traversal détecté")
return clean
4. Exécuter dans un sandbox isolé
L’agent MCP ne doit jamais tourner en root. L’executer dans un conteneur avec un utilisateur dédié non-privilégié, un filesystem en lecture seule, sans accès réseau sortant, et avec un timeout strict sur toutes les exécutions.
# docker-compose.yml
services:
mcp-agent:
user: "1000:1000"
read_only: true
network_mode: none
tmpfs:
- /tmp:size=100m
5. Auditer chaque exécution
Toute commande exécutée par un agent MCP doit être loguée avec son contexte complet : utilisateur, timestamp, commande, arguments, code de retour. Ces logs sont envoyés vers un SIEM et des alertes déclenchées en cas d’accès à des fichiers sensibles (/etc/shadow, .ssh/, variables d’environnement contenant KEY ou SECRET).
Quelques références pour aller plus loin
À retenir
