
Endurecimiento de la cadena de suministro de Capa 2 para servidores MCP — manifiestos de herramientas firmados con Ed25519, atestación de spawn en tiempo de ejecución, saneador de argumentos con denegación por defecto. Protege contra el envenenamiento del marketplace + CVE-2025-69256 + CVE-2025-61591.
Parte del StudioMeyer MCP Stack — Hecho en Mallorca 🌴 · ⭐ si lo usas
Respuesta directa a:
child_process.exec().Este paquete proporciona lo que Anthropic decidió no ofrecer: verificación criptográfica de qué herramientas puede exponer un servidor y qué llamadas de spawn puede realizar. Es una dependencia de sustitución directa, no un reemplazo del runtime.
Llevamos dos años construyendo herramientas y sistemas para nosotros mismos. Que este repositorio sea pequeño y tenga pocas estrellas no se debe a que sea nuevo. Se debe a que hace poco que decidimos compartir lo que hemos construido. No es un experimento reciente, es una historia larga con un commit reciente.
Nos encanta construir cosas y compartirlas. No nos gustan las tácticas de redes sociales, los trucos de crecimiento ni perseguir estrellas y seguidores. Por eso este repositorio es pequeño. El código es real, se usa y las incidencias se responden. Juzga por ti mismo.
Si te resulta útil, compartirlo, probarlo y dar tu opinión nos ayuda. Si podría ser mejor, una incidencia es más útil. Si construyes algo con él, cuéntanoslo en [email protected]. Eso de verdad nos alegra el día.
Desde un pequeño estudio en Palma de Mallorca.
npm install mcp-server-attestation
# CLI:
npm install -g mcp-attest-cli
# Reference MCP server:
npx mcp-attest-demo
Node 20+. Sin dependencias criptográficas externas: usa primitivas Ed25519 de node:crypto.
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 });
Esa es toda la integración. Dos llamadas a funciones, sin SaaS, sin daemon.
Si prefieres volver a verificar la firma en cada spawn (defensa en profundidad contra que un manifiesto no verificado o sustituido llegue a la compuerta), usa en su lugar la única llamada a prueba de fallos: verifica y luego atesta:
import { attestSpawnVerified, type SignedManifest } from "mcp-server-attestation";
attestSpawnVerified(signed as SignedManifest, { command, args });
mcp-attest-demo)Las anotaciones son honestas: attest_sign_manifest y attest_keygen escriben archivos en el disco, por lo que no son de solo lectura, pero no destruyen datos existentes, por lo que destructiveHint se mantiene en false. Consulta docs/THREAT-MODEL.md para ver la tabla de capacidades por herramienta.
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 sale con código 2 ante una firma incorrecta y con código 3 ante una discrepancia de pin.
| Versión de la especificación | Estado |
|---|---|
| 2024-11-05 | analizable en el manifiesto, no es objetivo del servidor de referencia |
| 2025-03-26 | analizable en el manifiesto, no es objetivo del servidor de referencia |
| 2025-06-18 | objetivo completo |
La librería es agnóstica al transporte. El servidor de referencia es solo stdio.
~/.mcp-attest/trust.json (anulación: MCP_ATTEST_TRUST_FILE). Las verificaciones posteriores rechazan cualquier clave nueva para el mismo nombre de servidor con TRUST_PIN_MISMATCH. Esto bloquea el vector de actualización maliciosa al estilo Cursor.--sigstore para contrastar la huella de la clave pública con el registro de transparencia Rekor de Sigstore.shellSafeString bloquea todos los metacaracteres ASCII de shell, NUL, CR, LF, VT, FF, NEL, caracteres de ancho cero, BOM, anulaciones RTL/LTR, aisladores Trojan-Source y confundibles latinos de ancho completo. El comportamiento de lista de permitidos requiere los tipos de regla explícitos regex / enum / prefix / literal.regex seguras frente a ReDoS. El patrón de una regla está firmado por el autor, pero el valor del argumento lo controla el atacante. El saneador detecta estáticamente los patrones propensos a retroceso (cuantificadores anidados sin límite como ) y se niega a ejecutarlos, por lo que un único argumento manipulado no puede congelar la ruta crítica del spawn. Las reglas también llevan un límite de entrada (4096 por defecto).Lo que este paquete NO hace (fuera del alcance):
mcp-oauth-shield).npm install
npm run typecheck
npm test
El corpus de pruebas incluye fixtures de reproducción de CVE (packages/lib/tests/fixtures/cve-2025-69256-payloads.json, cve-2025-61591-payloads.json). La compilación es una comprobación de regresión: todos los payloads deben bloquearse.
--provenance.mcp-server-attestation.StudioMeyer es un estudio de diseño e IA con sede en Palma de Mallorca que trabaja con clientes de todo el mundo. Creamos sitios web personalizados e infraestructura de IA para pequeñas y medianas empresas. Stack de producción sobre Claude Agent SDK, MCP y n8n, con Sentry, Langfuse y LangGraph para la observabilidad y una capa de protección propia.
MIT, Copyright 2026 Matthias Meyer (StudioMeyer). Consulta LICENSE.
| Paquete | Propósito |
|---|
mcp-server-attestation (packages/lib) | Librería: firma/verificación Ed25519, esquema de manifiesto, saneador, atestador de spawn, almacén de confianza TOFU. |
mcp-attest-cli (packages/cli) | CLI mcp-attest: keygen, sign, verify, inspect, fingerprint, check-pin. |
mcp-attest-demo (packages/demo-server) | Servidor MCP de referencia (stdio, spec 2025-06-18) que expone 5 herramientas que demuestran la librería. |
| # | Nombre | 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 |
regex(a+)+regexmaxLengthprefix seguras frente a traversal. Las reglas prefix rechazan los componentes de ruta .. por defecto (denyTraversal: true, incluida la forma codificada %2e%2e), por lo que /safe/../../etc/passwd se bloquea aunque cumpla prefix: "/safe/".attestSpawnVerified comprueba la firma del manifiesto antes de atestar el spawn en una única llamada a prueba de fallos: úsala en lugar de attestSpawnStrict a menos que hayas sacado la verificación Ed25519 por spawn de un bucle realmente crítico.