
Готовое исправление для неисправленной уязвимости внедрения команд MCP STDIO (семейство CVE-2026-30623)
Готовое исправление для непатченной уязвимости инъекции команд в MCP STDIO (семейство CVE-2026-30623, раскрытое OX Security в апреле 2026 года как «by design» — патча SDK не будет). Добавьте одну строку импорта — и каждый stdio MCP-сервер, запускаемый вашим Python-приложением, будет проверяться по команде/аргументам/окружению до того, как ОС породит процесс.
Если вы здесь впервые, сначала прочитайте Область применения, затем Установка и Начало работы — они обеспечат вашу защиту менее чем за две минуты.
Pre-1.0, идёт активная разработка.
check/launch/rules) реализованы и покрыты автоматическим набором тестов, которые выполняются против реальных бинарных файлов, установленных на тестовой машине (python, node, npx), — не моков, — включая настоящее сквозное MCP-рукопожатие через реальный запускаемый серверный фикстур и настоящий тест launch на уровне субпроцесса.Что входит в область применения: валидация запуска stdio MCP-сервера (команда + аргументы + окружение) до того, как он достигнет уровня порождения процессов ОС, — в частности для закрытия пути инъекции команд/аргументов, описанного в SECURITY.md.
Что явно вне области применения: сканирование объявленных инструментов сервера на опасные возможности (это другая проблема — см. AgentGuard), помещение запущенного процесса в песочницу и не-stdio (SSE/HTTP) MCP-транспорты.
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)
Проверьте, что всё работает:
mcpshield --version
mcpshield --help
Если ваше приложение написано на Python и само создаёт StdioServerParameters / вызывает mcp.client.stdio.stdio_client, добавьте один импорт в самый верх вашей точки входа — до того, как что-либо ещё импортирует 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
Теперь небезопасный запуск вызывает mcpshield.core.errors.UnsafeConfigurationError (подкласс ValueError) вместо порождения процесса.
Проверьте конфигурационный файл в стиле mcpServers, ничего не запуская:
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
Завершается с ненулевым кодом, если что-либо имеет статус BLOCKED (добавьте --strict, чтобы также завершаться с ошибкой при WARN) — можно сразу встраивать в CI.
Для MCP-клиента (Node, Java, Rust, ...), который не может использовать Python-автопатч, укажите в его конфиге mcpshield вместо реальной команды:
{
"command": "mcpshield",
"args": ["launch", "--", "npx", "-y", "some-mcp-server"]
}
launch выполняет валидацию, затем запускает реальную команду с тем же stdio, которого ожидает ваш MCP-клиент (прозрачная передача), — или отказывается с понятной ошибкой, если запуск небезопасен.
Нативные бинарные файлы получают менее строгие проверки аргументов, поскольку они выполняют exec напрямую — оболочки, которая заново разбирала бы список аргументов, нет. Команды, интерпретируемые оболочкой (чаще всего npx.cmd/npx.bat в Windows), получают строгие проверки, потому что это и есть тот самый механизм, который эксплуатирует соответствующая CVE.
Оба варианта — это осознанные исключения, включаемые для конкретных значений, а не универсальный флаг «отключить проверки»:
allow_raw_args=["--some-value-with-a-pipe"] (библиотека) освобождает конкретные значения аргументов, которые вы проверили и которым доверяете.allow_env=["SOME_VAR"] позволяет переменной окружения, которая обычно удаляется, проходить без изменений.git clone.mcp.client.stdio.stdio_client в том виде, в котором он найден на момент патча. Код, который уже держит собственную ссылку (через from mcp.client.stdio import stdio_client, выполненный до import mcpshield.autopatch), обойдёт его — всегда импортируйте mcpshield.autopatch первым.check разрешает команды, опираясь на ту машину, на которой он запущен. Конфиг, который разрешался бы иначе на машине, куда он фактически развёрнут (другой PATH, другие установленные инструменты), может давать там иные результаты.mcpshield/
autopatch.py # one-line-import fix for Python MCP hosts
core/
validate.py # the validation engine (command/args/env checks)
rules.py # blocklist/allowlist data
errors.py # UnsafeConfigurationError
cli/
main.py
commands/ (check.py, launch.py, rules.py)
tests/
fixtures/ # real benign MCP server + sample/malicious configs
pip install -e ".[dev,mcp]"
pytest
Тестовый набор выполняет проверки против реальных бинарных файлов python/node/npx, установленных на машине, где он запускается (разрешаемых тем же способом, каким их разрешает сам движок), и включает настоящее сквозное MCP-рукопожатие через реальный запускаемый серверный фикстур — без моков.
| Проверка | Нативный бинарный файл (например, python.exe) | Интерпретируемый оболочкой (.cmd/.bat/shebang-скрипт) |
|---|
Метасимволы оболочки (&, |, ;, обратный апостроф, $(...), ...) в аргументе | Разрешено | Заблокировано |
| NUL-байт / перевод строки в аргументе | Заблокировано | Заблокировано |
Команда разрешается через относительный обход пути (..) | Заблокировано | Заблокировано |
| Команда не разрешается в реальный файл | Заблокировано | Заблокировано |
LD_PRELOAD / NODE_OPTIONS / и т.п. в окружении | Удаляется (предупреждение) | Удаляется (предупреждение) |
PYTHONPATH в окружении | Помечается (предупреждение), не удаляется | Помечается (предупреждение), не удаляется |
| Команда | Что делает |
|---|
mcpshield check <config> [--format table|json] [--strict] | Статическая проверка конфига mcpServers. Ничего не выполняет. Ненулевой код возврата при любом BLOCKED (а с --strict — и при WARN). |
mcpshield launch -- <command> [args...] | Выполняет валидацию, затем запускает реальную команду с прозрачной передачей stdio. |
mcpshield rules list | Показывает активный блок-лист метасимволов оболочки, списки переменных окружения и известные безопасные бинарные файлы-лаунчеры. |