
Correctif de substitution pour la faille non corrigée d'injection de commandes MCP STDIO (famille CVE-2026-30623)
Un correctif prêt à l'emploi pour la faille d'injection de commande MCP STDIO non corrigée (la famille CVE-2026-30623, divulguée par OX Security en avril 2026 comme « by design » — aucun correctif SDK n'est prévu). Importez une ligne, et chaque serveur MCP stdio que votre application Python lance voit sa commande/ses arguments/son environnement validés avant que l'OS ne crée un processus.
Si vous êtes nouveau ici, lisez d'abord Périmètre, puis Installation et Démarrage rapide vous protégeront en moins de deux minutes.
Pré-1.0, développé activement.
check/launch/rules) sont implémentés et couverts par une suite de tests automatisés qui s'exécute contre les vrais binaires installés sur la machine de test (python, node, npx) — pas des mocks — y compris un véritable handshake MCP de bout en bout via un fixture de serveur réellement lancé, et un véritable test au niveau sous-processus de launch.Dans le périmètre : valider le lancement d'un serveur MCP stdio (commande + arguments + environnement) avant qu'il n'atteigne la couche de création de processus de l'OS, afin de fermer spécifiquement la voie d'injection de commande/arguments décrite dans SECURITY.md.
Explicitement hors périmètre : l'analyse des outils déclarés d'un serveur pour détecter des capacités risquées (c'est un autre problème — voir AgentGuard), le sandboxing du processus lancé, et les transports MCP non-stdio (SSE/HTTP).
git clone <this-repo>
cd mcpshield
pip install -e . # core CLI: click + rich only
pip install -e ".[mcp]" # if you also want the Python autopatch (needs the `mcp` SDK)
Vérifiez que cela fonctionne :
mcpshield --version
mcpshield --help
Si votre application est écrite en Python et construit StdioServerParameters / appelle mcp.client.stdio.stdio_client elle-même, ajoutez un import tout en haut de votre point d'entrée — avant que quoi que ce soit d'autre n'importe mcp.client.stdio :
import mcpshield.autopatch # side-effect import; must come first
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
# ... use stdio_client exactly as before -- it's now validated
Un lancement non sûr lève désormais mcpshield.core.errors.UnsafeConfigurationError (une sous-classe de ValueError) au lieu de jamais créer de processus.
Auditez un fichier de configuration de type mcpServers sans rien exécuter :
mcpshield check claude_desktop_config.json
+---------------------------------------------------------------+
| Server | Status | Command | Detail |
|------------------+---------+---------+------------------------|
| filesystem | OK | npx | - |
| evil-server | BLOCKED | npx | Argument '...' contains|
| | | | shell metacharacter |
+---------------------------------------------------------------+
1 ok, 0 warned, 1 blocked
Renvoie un code de sortie non nul si quelque chose est BLOCKED (ajoutez --strict pour échouer aussi sur WARN) — intégrez-le directement dans votre CI.
Pour un client MCP (Node, Java, Rust, ...) qui ne peut pas utiliser l'autopatch Python, pointez sa configuration vers mcpshield au lieu de la vraie commande :
{
"command": "mcpshield",
"args": ["launch", "--", "npx", "-y", "some-mcp-server"]
}
launch valide, puis exécute la vraie commande avec le même stdio que votre client MCP attend (pass-through transparent) — ou refuse avec une erreur claire si le lancement est non sûr.
| Vérification | Binaire natif (p. ex. python.exe) | Interprétable par le shell (.cmd/.bat/script shebang) |
|---|---|---|
Métacaractères shell (&, |, ;, backtick, $(...), ...) dans un argument | Autorisé | Bloqué |
| Octet NUL / saut de ligne dans un argument | Bloqué | Bloqué |
La commande se résout via un parcours de chemin relatif (..) | Bloqué | Bloqué |
| La commande ne se résout pas vers un fichier réel | Bloqué | Bloqué |
LD_PRELOAD / NODE_OPTIONS / etc. dans l'environnement | Supprimé (avertissement) | Supprimé (avertissement) |
PYTHONPATH dans l'environnement | Signalé (avertissement), non supprimé | Signalé (avertissement), non supprimé |
Les binaires natifs bénéficient de vérifications d'arguments plus souples car ils font un exec direct — il n'y a pas de shell pour réinterpréter la liste d'arguments. Les commandes interprétables par le shell (le plus souvent npx.cmd/npx.bat sur Windows) font l'objet de contrôles stricts car c'est exactement le mécanisme exploité par la CVE sous-jacente.
Les deux sont des opt-in délibérés, valeur par valeur — jamais un drapeau global « désactiver les vérifications » :
allow_raw_args=["--some-value-with-a-pipe"] (bibliothèque) exempte des valeurs d'arguments spécifiques que vous avez examinées et auxquelles vous faites confiance.allow_env=["SOME_VAR"] permet à une variable d'environnement normalement supprimée de passer inchangée.| Commande | Fonction |
|---|---|
mcpshield check <config> [--format table|json] [--strict] | Audit statique d'une configuration mcpServers. N'exécute jamais rien. Sortie non nulle en cas de BLOCKED (ou WARN aussi, avec --strict). |
mcpshield launch -- <command> [args...] | Valide, puis exécute la vraie commande avec un stdio en pass-through. |
mcpshield rules list | Affiche la liste noire active des métacaractères shell, les listes de variables d'environnement et les binaires de lancement sûrs connus. |