
mcp-server-attestation v0.2.0
Indurimento della catena di fornitura Layer-2 per server MCP — manifesti degli strumenti firmati con Ed25519, attestazione di spawn runtime, sanitizzatore di argomenti default-deny. Difende contro l'avvelenamento del marketplace + CVE-2025-69256 + CVE-2025-61591.
Parte dello StudioMeyer MCP Stack — Costruito a Maiorca 🌴 · ⭐ se lo usi
mcp-server-attestation
Rafforzamento della supply chain di Layer-2 per i server Model Context Protocol. Manifest degli strumenti firmati con Ed25519, attestazione runtime degli spawn, sanitizer degli argomenti con negazione predefinita.
Risposta diretta a:
- OX Security marketplace-poisoning, Aprile 2026 — 9 degli 11 registri MCP hanno accettato server dannosi. Posizione pubblica di Anthropic: 'comportamento atteso'.
- CVE-2025-69256 — Serverless Framework MCP RCE tramite iniezione di comandi in
child_process.exec(). - CVE-2025-61591 — Cursor MCP RCE tramite server dannoso installato via OAuth con dirottamento degli spawn.
Questo pacchetto fornisce ciò che Anthropic ha scelto di non fornire: verifica crittografica di quali strumenti un server può esporre e quali chiamate di spawn può effettuare. È una dipendenza plug-and-play, non un sostituto runtime.
Una nota da parte nostra
Costruiamo strumenti e sistemi per noi stessi da due anni. Il fatto che questa repo sia piccola e abbia poche stelle non è perché è nuova. È perché abbiamo deciso solo ora di condividere ciò che abbiamo costruito. Non è un esperimento fresco, è una lunga storia con un commit recente.
Amiamo costruire cose e condividerle. Non amiamo le tattiche dei social media, i growth hack o inseguire stelle e follower. Quindi questa repo è piccola. Il codice è reale, viene utilizzato, le issue ricevono risposta. Giudica tu stesso.
Se ti aiuta, condividere, testare e dare feedback ci aiuta. Se potrebbe essere migliore, un'issue è più utile. Se ci costruisci qualcosa sopra, diccelo a [email protected]. Ci rallegra davvero la giornata.
Da un piccolo studio a Palma di Maiorca.
Pacchetti (npm workspaces)
| Package | Scopo |
|---|---|
mcp-server-attestation (packages/lib) | Libreria: firma/verifica Ed25519, schema manifest, sanitizer, attestatore spawn, trust store TOFU. |
mcp-attest-cli (packages/cli) | CLI mcp-attest: keygen, sign, verify, inspect, fingerprint, check-pin. |
mcp-attest-demo (packages/demo-server) | Server MCP di riferimento (stdio, specifica 2025-06-18) che espone 5 strumenti che dimostrano la libreria. |
Installa
npm install mcp-server-attestation
# CLI:
npm install -g mcp-attest-cli
# Server MCP di riferimento:
npx mcp-attest-demo
Node 20+. Nessuna dipendenza crittografica esterna — utilizza le primitive Ed25519 di node:crypto.
Avvio rapido del server in cinque righe
import { verifyManifestStrict, attestSpawnStrict, type SignedManifest } from "mcp-server-attestation";
import signed from "./signed/manifest.json" assert { type: "json" };
// 1. All'avvio: dimostra che il manifest che spedisci è quello che hai firmato.
verifyManifestStrict(signed);
// 2. Prima di ogni child_process.spawn:
attestSpawnStrict(signed as SignedManifest, { command, args });
Questa è l'intera integrazione. Due chiamate di funzione, nessun SaaS, nessun demone.
Se preferisci riverificare la firma ad ogni spawn (difesa in profondità contro un manifest non verificato o scambiato che raggiunge il gate), usa invece la singola chiamata fail-safe — verifica poi attesta:
import { attestSpawnVerified, type SignedManifest } from "mcp-server-attestation";
attestSpawnVerified(signed as SignedManifest, { command, args });
Strumenti (server di riferimento mcp-attest-demo)
| # | Nome | 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 |
Le annotazioni sono oneste: attest_sign_manifest e attest_keygen scrivono file su disco, quindi non sono di sola lettura, ma non distruggono dati esistenti, quindi destructiveHint rimane false. Vedi docs/THREAT-MODEL.md per la tabella delle capacità per strumento.
CLI
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 # cross-ref Rekor opzionale
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 esce con codice 2 su firma errata, codice 3 su mancata corrispondenza del pin.
Compatibilità con la specifica MCP
| Versione specifica | Stato |
|---|---|
| 2024-11-05 | analizzabile nel manifest, non obiettivo del server di riferimento |
| 2025-03-26 | analizzabile nel manifest, non obiettivo del server di riferimento |
| 2025-06-18 | obiettivo completo |
La libreria è indipendente dal trasporto. Il server di riferimento è solo stdio.
Modello di sicurezza
- Trust-on-First-Use è l'impostazione predefinita. La prima volta che verifichi un server, la sua chiave pubblica viene fissata a
~/.mcp-attest/trust.json(sovrascrivi:MCP_ATTEST_TRUST_FILE). Le verifiche successive rifiutano qualsiasi nuova chiave per lo stesso nome server conTRUST_PIN_MISMATCH. Questo intercetta il vettore di aggiornamento dannoso stile Cursor. - Nessuna lista di chiavi fidate inclusa. Questo pacchetto non funge da gatekeeper. Se desideri una garanzia più forte, opta per
--sigstoreper incrociare l'impronta della chiave pubblica con il registro di trasparenza Sigstore Rekor. - Sanitizer degli argomenti con negazione predefinita.
shellSafeStringblocca ogni metacarattere shell ASCII, NUL, CR, LF, VT, FF, NEL, caratteri a larghezza zero, BOM, override RTL/LTR, isolati Trojan-Source, e confondibili fullwidth-Latin. Il comportamento di allowlist richiede i tipi di regole espliciteregex/enum/prefix/literal. - Regole
regexsicure contro ReDoS. Il pattern di una regolaregexè firmato dall'autore, ma il valore dell'argomento è controllato dall'attaccante. Il sanitizer rileva staticamente i pattern soggetti a backtracking (quantificatori innestati illimitati come(a+)+) e si rifiuta di eseguirli, quindi un singolo argomento malformato non può bloccare il percorso caldo dello spawn. Le regoleregexhanno anche un limite massimo di inputmaxLength(default 4096). - Regole
prefixsicure contro traversal. Le regoleprefixrifiutano i componenti di percorso..per impostazione predefinita (denyTraversal: true, inclusa la forma codificata%2e%2e), quindi/safe/../../etc/passwdviene bloccato anche se soddisfaprefix: "/safe/". - Verifica poi attesta.
attestSpawnVerifiedcontrolla la firma del manifest prima di attestare lo spawn in un'unica chiamata fail-safe — usala invece diattestSpawnStricta meno che tu non abbia misurato la verifica Ed25519 per spawn fuori da un ciclo realmente caldo. - JSON canonico è la superficie firmata. La riserializzazione non può modificare i byte firmati.
Cosa questo pacchetto NON fa (fuori ambito):
- Isolare o containerizzare il processo server.
- Indurimento del flusso OAuth (build separata
mcp-oauth-shield). - Controllo del traffico di rete in uscita.
- Auto-patch dei server esistenti.
Test
npm install
npm run typecheck
npm test
Il corpus di test include fixture di replay CVE (packages/lib/tests/fixtures/cve-2025-69256-payloads.json, cve-2025-61591-payloads.json). La compilazione è un controllo di regressione: ogni payload deve essere bloccato.
Distribuzione
- Pubblicazione npm tramite GitHub Actions OIDC con
--provenance. - Server di riferimento inviato a mcp.so e FastMCP Directory.
- Libreria pubblicata separatamente come
mcp-server-attestation.
Informazioni su StudioMeyer
StudioMeyer è uno studio di AI e design con sede a Palma di Maiorca, che lavora con clienti in tutto il mondo. Costruiamo siti web personalizzati e infrastrutture AI per piccole e medie imprese. Stack di produzione su Claude Agent SDK, MCP e n8n, con Sentry, Langfuse e LangGraph per l'osservabilità e un layer di protezione interno.
Licenza
MIT, Copyright 2026 Matthias Meyer (StudioMeyer). Vedi LICENSE.