
Solución directa para la vulnerabilidad de inyección de comandos sin parchear en MCP STDIO (familia CVE-2026-30623)
Un parche de integración directa para la vulnerabilidad sin parchear de inyección de comandos en MCP STDIO (la familia CVE-2026-30623, divulgada por OX Security en abril de 2026 como "por diseño" -- no llegará ningún parche del SDK). Importa una línea, y cada servidor MCP stdio que lance tu aplicación Python verá su command/args/env validado antes de que el SO llegue a crear un proceso.
Si eres nuevo aquí, lee primero Alcance, luego Instalación y Primeros pasos te protegerán en menos de dos minutos.
Pre-1.0, en desarrollo activo.
check/launch/rules) están
implementados y cubiertos por una suite de pruebas automatizada que se ejecuta contra los
binarios reales instalados en la máquina de pruebas (python, node, npx) --
no mocks -- incluyendo un auténtico handshake MCP de extremo a extremo a través de un
fixture real de servidor lanzado, y una prueba genuina a nivel de subproceso de launch.Dentro del alcance: validar el lanzamiento de un servidor MCP stdio (command + args + env) antes de que llegue a la capa de creación de procesos del SO, para cerrar concretamente la vía de inyección de comandos/argumentos descrita en SECURITY.md.
Explícitamente fuera del alcance: escanear las herramientas declaradas de un servidor en busca de capacidades riesgosas (eso es un problema distinto -- consulta AgentGuard), el sandboxing del proceso lanzado y los transportes MCP que no son 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)
Comprueba que funciona:
mcpshield --version
mcpshield --help
Si tu aplicación está escrita en Python y construye StdioServerParameters /
llama a mcp.client.stdio.stdio_client por sí misma, añade un import al
principio de tu punto de entrada -- antes de que cualquier otra cosa 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 lanzamiento inseguro ahora lanza mcpshield.core.errors.UnsafeConfigurationError
(una subclase de ValueError) en lugar de llegar a crear un proceso.
Audita un archivo de configuración de estilo mcpServers sin ejecutar nada:
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
Sale con código distinto de cero si algo está BLOCKED (añade --strict para que también falle
con WARN) -- puedes integrarlo directamente en tu CI.
Para un cliente MCP (Node, Java, Rust, ...) que no pueda usar el parche
automático de Python, apunta su configuración a mcpshield en lugar del comando real:
{
"command": "mcpshield",
"args": ["launch", "--", "npx", "-y", "some-mcp-server"]
}
launch valida y después ejecuta el comando real con el mismo stdio
que tu cliente MCP espera (paso transparente) -- o se niega con un
error claro si el lanzamiento no es seguro.
| Comprobación | Binario nativo (p. ej. python.exe) | Interpretable por shell (script .cmd/.bat/shebang) |
|---|---|---|
Metacaracteres de shell (&, |, ;, comilla invertida, $(...), ...) en un argumento | Permitido | Bloqueado |
| Byte NUL / salto de línea en un argumento | Bloqueado | Bloqueado |
El comando se resuelve mediante path traversal relativo (..) | Bloqueado | Bloqueado |
| El comando no se resuelve a un archivo real | Bloqueado | Bloqueado |
LD_PRELOAD / NODE_OPTIONS / etc. en env | Eliminado (advertencia) | Eliminado (advertencia) |
PYTHONPATH en env | Marcado (advertencia), no eliminado | Marcado (advertencia), no eliminado |
Los binarios nativos reciben comprobaciones de argumentos más laxas porque hacen exec directamente --
no hay shell que vuelva a interpretar la lista de argumentos. Los comandos interpretables por shell
(lo más habitual: npx.cmd/npx.bat en Windows) reciben comprobaciones estrictas
porque ese es exactamente el mecanismo que explota la CVE subyacente.
Ambas son opciones deliberadas de aceptación por valor -- nunca una bandera genérica de "desactivar comprobaciones":
allow_raw_args=["--some-value-with-a-pipe"] (librería) exime valores de argumento
específicos que hayas revisado y en los que confíes.allow_env=["SOME_VAR"] permite que una variable de entorno normalmente eliminada
pase sin modificaciones.| Comando | Qué hace |
|---|---|
mcpshield check <config> [--format table|json] [--strict] | Auditoría estática de una configuración mcpServers. Nunca ejecuta nada. Sale con código distinto de cero ante cualquier BLOCKED (o también WARN, con --strict). |
mcpshield launch -- <command> [args...] | Valida y después ejecuta el comando real con pass-through de stdio. |
mcpshield rules list | Muestra la lista negra activa de metacaracteres de shell, las listas de variables de entorno y los binarios lanzadores seguros conocidos. |