
Статический и динамический сканер безопасности для серверов MCP (Model Context Protocol).
Сканер безопасности, сочетающий статический и динамический (runtime) анализ MCP-серверов (Model Context Protocol). В период с января по апрель 2026 года исследователи безопасности раскрыли более 40 CVE в реализациях MCP-серверов, а сканирование публичных MCP-серверов, проведённое Endor Labs в 2026 году, показало, что 82% серверов уязвимы как минимум к одному классу риска OWASP MCP Top 10, у 67% обнаружены приёмники (sink), уязвимые к обходу пути или инъекциям, а 34% используют жёстко заданные или избыточно привилегированные учётные данные — отдельные исследования оценивают долю серверов, работающих вообще без аутентификации, примерно в 38–40%.
Docker:
docker build -t sentrymcp .
docker run --rm -v "$(pwd):/scan" sentrymcp scan /scan
(PowerShell: docker run --rm -v ${PWD}:/scan sentrymcp scan /scan)
Из исходников:
git clone https://github.com/zaydmulani09/sentrymcp.git && cd sentrymcp
cargo build --release
./target/release/sentrymcp scan <path>
Примечание для Windows: если набор инструментов rustc по умолчанию — -gnu и сборка завершается ошибкой dlltool.exe not found, один раз в каталоге репозитория переключитесь на MSVC: rustup override set stable-x86_64-pc-windows-msvc.
Реальный вывод на синтетическом примере обхода пути в corpus/:
$ sentrymcp scan corpus/vulnerable-git-server
== Code Vulnerabilities ==
[HIGH] mcp_server_git/server.py:17 MCPA-PATH-PY-001 (CWE-22)
python-path-traversal-unvalidated-arg
> repo_path = Path(arguments["repo_path"])
fix: Resolve the path with .resolve() and verify containment (e.g. path.resolve().is_relative_to(allowed_root)) before using it, or reject paths containing '..'.
[HIGH] mcp_server_git/server.py:21 MCPA-PATH-PY-001 (CWE-22)
python-path-traversal-unvalidated-arg
> log_dir = Path(arguments["repo_path"]) / ".git" / "logs"
fix: Resolve the path with .resolve() and verify containment (e.g. path.resolve().is_relative_to(allowed_root)) before using it, or reject paths containing '..'.
summary (code vulnerabilities): 2 findings — 0 critical, 2 high, 0 medium, 0 low
total: 2 findings
| Категория | Что обнаруживает | Пример |
|---|---|---|
| Уязвимости кода | Обход пути, внедрение shell-команд, небезопасный eval/exec | Path(arguments["repo_path"]) используется без проверки на ограничение корневой директорией |
| Отравление инструментов | Скрытые инструкции, невидимые/гомоглифные unicode-символы, раздутые описания, спрятанные в метаданных инструмента | Описание инструмента вида «...игнорируй предыдущие инструкции, не сообщай пользователю...» |
| Аутентификация и права | Отсутствие аутентификации в сетевых транспортах, жёстко заданные учётные данные, утечка учётных данных через логирование, избыточно широкая область действия | api_key = "sk-live-..." захардкожена в коде вместо чтения из окружения |
| Динамический прокси | Подмена описания инструмента («rug pull») и неожиданные исходящие соединения, наблюдаемые в реальном времени | Описание description инструмента меняется между первым и последующим ответом tools/list в рамках одной сессии |
sentrymcp scan <path> покрывает первые три категории (статически, только по исходному коду). sentrymcp proxy -- <target cmd> покрывает четвёртую (динамически): прокси располагается между MCP-клиентом и реальным сервером через stdio, прозрачно ретранслируя трафик и ведя наблюдение.
Одно рабочее пространство Cargo, четыре крейта:
sentrymcp-core — механизм сопоставления правил, сканер каталогов, извлечение описаний инструментов.sentrymcp-rules — каждое правило обнаружения в виде TOML (серьёзность, ссылка на CWE/OWASP, способ устранения) — никакие шаблоны обнаружения не захардкожены в Rust.sentrymcp-proxy — динамический ретранслятор stdio, сравнение (diff) ответов tools/list и наблюдатель за сетью (best-effort).sentrymcp-cli — единый бинарный файл sentrymcp (подкоманды scan и proxy).Более подробные заметки по дизайну и известные ограничения каждого механизма находятся в doc-комментариях соответствующих крейтов (engine.rs, extract.rs, netwatch.rs).
netstat); на других платформах он всегда сообщает о нулевом количестве соединений — это задокументированный пробел, а не скрытая ошибка.heuristic (missing-auth, homoglyph, overprivileged-scope) — это подсказки для проверки, а не подтверждённые вердикты; ложные срабатывания здесь ожидаемы по замыслу.Форкайте, создавайте ветку, открывайте PR. Держите новые правила обнаружения в TOML, а не в Rust, и добавляйте пару «уязвимый/исправленный» в corpus/ для всего нового.
MIT — см. LICENSE.