
Укрепление цепочки поставок уровня 2 для MCP-серверов — манифесты инструментов с подписью Ed25519, аттестация запуска процессов во время выполнения, санитайзер аргументов с запретом по умолчанию. Защищает от отравления маркетплейса + CVE-2025-69256 + CVE-2025-61591.
<!-- studiomeyer-mcp-stack-banner:start --> > **Часть [StudioMeyer MCP Stack](https://studiomeyer.io)** — Создано на Мальорке 🌴 · ⭐ если используете <!-- studiomeyer-mcp-stack-banner:end --> # mcp-server-attestation <!-- badges --> [](https://www.npmjs.com/package/mcp-server-attestation) [](https://www.npmjs.com/package/mcp-server-attestation)    <!-- /badges -->Укрепление безопасности цепочки поставок уровня 2 для серверов Model Context Protocol. Манифесты инструментов с подписью Ed25519, аттестация spawn-вызовов в рантайме, санитайзер аргументов с политикой «запрет по умолчанию» (default-deny). Прямой ответ на: - **OX Security: отравление маркетплейса, апрель 2026** — 9 из 11 MCP-реестров приняли вредоносные серверы. Опубликованная позиция Anthropic: «ожидаемое поведение». - **CVE-2025-69256** — RCE в Serverless Framework MCP через внедрение команд в `child_process.exec()`. - **CVE-2025-61591** — RCE в Cursor MCP через установленный через OAuth вредоносный сервер с перехватом spawn-вызова. Этот пакет предоставляет то, что Anthropic решил не делать: криптографическую проверку того, какие инструменты серверу разрешено предоставлять и какие spawn-вызовы ему разрешено совершать. Это drop-in зависимость, а не замена среды выполнения. ## Примечание от нас Последние два года мы создавали инструменты и системы для себя. То, что этот репозиторий небольшой и у него мало звёзд, — не потому что он новый. А потому, что мы лишь недавно решили поделиться тем, что построили. Это не свежий эксперимент, это длинная история с недавним коммитом. Мы любим создавать и делиться. Мы не любим тактики из соцсетей, growth-хаки и погоню за звёздами и подписчиками. Поэтому репозиторий небольшой. Код настоящий, он используется, на issues отвечают. Судите сами. Если он помогает вам — нам помогают распространение, тестирование и обратная связь. Если его можно улучшить — issue полезнее. Если вы создадите что-то на его основе, напишите нам на [email protected]. Это и правда делает наш день. Из небольшой студии в Пальма-де-Мальорке. ## Пакеты (npm workspaces) | Пакет | Назначение | | --- | --- | | `mcp-server-attestation` (`packages/lib`) | Библиотека: подпись/проверка Ed25519, схема манифеста, санитайзер, аттестатор spawn, хранилище доверия TOFU. | | `mcp-attest-cli` (`packages/cli`) | CLI `mcp-attest`: `keygen`, `sign`, `verify`, `inspect`, `fingerprint`, `check-pin`. | | `mcp-attest-demo` (`packages/demo-server`) | Эталонный MCP-сервер (stdio, спецификация 2025-06-18), предоставляющий 5 инструментов, демонстрирующих библиотеку. | ## Установка ```bash npm install mcp-server-attestation # CLI: npm install -g mcp-attest-cli # Reference MCP server: npx mcp-attest-demo ``` Node 20+. Без внешних криптозависимостей — используются примитивы Ed25519 из `node:crypto`. ## Быстрый старт: сервер из пяти строк ```ts import { verifyManifestStrict, attestSpawnStrict, type SignedManifest } from "mcp-server-attestation"; import signed from "./signed/manifest.json" assert { type: "json" }; // 1. At startup: prove the manifest you ship is the manifest you signed. verifyManifestStrict(signed); // 2. Before every child_process.spawn: attestSpawnStrict(signed as SignedManifest, { command, args }); ``` Это вся интеграция. Два вызова функций, никакого SaaS, никакого демона. Если вы предпочитаете перепроверять подпись при каждом spawn-вызове (эшелонированная защита от того, чтобы непроверенный или подменённый манифест достиг шлюза), используйте вместо этого единый отказоустойчивый вызов — он сначала проверяет подпись, *затем* аттестует: ```ts import { attestSpawnVerified, type SignedManifest } from "mcp-server-attestation"; attestSpawnVerified(signed as SignedManifest, { command, args }); ``` ## Инструменты (эталонный сервер `mcp-attest-demo`) | # | Имя | readOnlyHint | destructiveHint | | - | ---- | ------------ | --------------- | | 1 | `attest_verify_manifest` | true | false | | 2 | `attest_inspect_spawn` | true | false | | 3 | `attest_generate_manifest_template` | true | false | | 4 | `attest_sign_manifest` | false | false | | 5 | `attest_keygen` | false | false | Аннотации честные: `attest_sign_manifest` и `attest_keygen` записывают файлы на диск, поэтому они не только для чтения, но они не уничтожают существующие данные, поэтому destructiveHint остаётся false. См. `docs/THREAT-MODEL.md` — таблицу возможностей для каждого инструмента. ## CLI ```bash mcp-attest keygen --out-dir ./keys --name prod mcp-attest sign --manifest manifest.json --private-key keys/prod.key --out signed.json mcp-attest verify --signed signed.json --pin # TOFU pin mcp-attest verify --signed signed.json --sigstore # opt-in Rekor cross-ref mcp-attest inspect --signed signed.json --command /usr/bin/echo --arg "hello" mcp-attest fingerprint --public-key keys/prod.pub mcp-attest check-pin --server my-server --signed signed.json ``` `verify` завершается с кодом 2 при неверной подписи и с кодом 3 при несовпадении пина. ## Совместимость со спецификацией MCP | Версия спецификации | Статус | | --- | --- | | 2024-11-05 | разбирается в манифесте, не является целью эталонного сервера | | 2025-03-26 | разбирается в манифесте, не является целью эталонного сервера | | 2025-06-18 | полная цель | Библиотека не зависит от транспорта. Эталонный сервер работает только через stdio. ## Модель безопасности - **Trust-on-First-Use (доверие при первом использовании)** — поведение по умолчанию. При первой проверке сервера его открытый ключ закрепляется в `~/.mcp-attest/trust.json` (переопределяется через `MCP_ATTEST_TRUST_FILE`). Последующие проверки отклоняют любой новый ключ для того же имени сервера с ошибкой `TRUST_PIN_MISMATCH`. Это перехватывает вектор вредоносного обновления в стиле Cursor. - **Нет встроенного списка доверенных ключей.** Этот пакет не выполняет роль привратника. Если нужны более строгие гарантии, включите `--sigstore`, чтобы перекрёстно сверить отпечаток открытого ключа с прозрачным журналом Sigstore Rekor. - **Санитайзер аргументов с политикой default-deny (запрет по умолчанию).** `shellSafeString` блокирует все ASCII-метасимволы оболочки, NUL, CR, LF, VT, FF, NEL, символы нулевой ширины, BOM, переопределения RTL/LTR, изоляторы Trojan Source и fullwidth-латинские конфузабельные символы. Поведение белого списка требует явных типов правил `regex` / `enum` / `prefix` / `literal`. - **ReDoS-безопасные правила `regex`.** Паттерн правила `regex` подписан автором, но значение аргумента контролируется атакующим. Санитайзер статически обнаруживает паттерны, склонные к бэктрекингу (вложенные неограниченные квантификаторы вроде `(a+)+`), и отказывается их выполнять, поэтому один специально сформированный аргумент не может заморозить горячий путь spawn. Правила `regex` также имеют ограничение длины ввода `maxLength` (по умолчанию 4096). - **Устойчивые к обходу каталогов правила `prefix`.** Правила `prefix` по умолчанию отклоняют компоненты пути `..` (`denyTraversal: true`, включая закодированную форму `%2e%2e`), поэтому `/safe/../../etc/passwd` блокируется, даже если удовлетворяет `prefix: "/safe/"`. - **Сначала проверка, затем аттестация.** `attestSpawnVerified` проверяет подпись манифеста перед аттестацией spawn-вызова в одном отказоустойчивом вызове — используйте его вместо `attestSpawnStrict`, если только вы по результатам замеров не вынесли попер-вызовную проверку Ed25519 из по-настоящему горячего цикла. - **Канонический JSON** — это подписываемая поверхность. Повторная сериализация не может изменить подписанные байты. Что этот пакет НЕ делает (вне области применения): - Изоляция процесса сервера в песочнице или контейнере. - Усиление OAuth-потока (отдельная сборка `mcp-oauth-shield`). - Контроль исходящего сетевого трафика. - Автопатчинг существующих серверов. ## Тесты ```bash npm install npm run typecheck npm test ``` Тестовый корпус включает фикстуры воспроизведения CVE-атак (`packages/lib/tests/fixtures/cve-2025-69256-payloads.json`, `cve-2025-61591-payloads.json`). Сборка — это регрессионная проверка: каждый payload должен быть заблокирован. ## Распространение - Публикация в npm через GitHub Actions OIDC с флагом `--provenance`. - Эталонный сервер размещён в mcp.so и FastMCP Directory. - Библиотека публикуется отдельно под именем `mcp-server-attestation`. ## О StudioMeyer [StudioMeyer](https://studiomeyer.io) — студия AI и дизайна, базирующаяся в Пальма-де-Мальорке и работающая с клиентами по всему миру. Мы создаём заказные веб-сайты и AI-инфраструктуру для малого и среднего бизнеса. Продакшн-стек: Claude Agent SDK, MCP и n8n, с Sentry, Langfuse и LangGraph для наблюдаемости и собственным защитным слоем. ## Лицензия MIT, © 2026 Matthias Meyer (StudioMeyer). См. `LICENSE`.