Sigil

Camada de confiança para servidores MCP: varredura de segurança estática e comportamental, fuzzing e selos com versão fixada assinados por Ed25519 publicados em um índice público baseado em git.

Documentação

Sigil

ci

Verificação de confiança para servidores MCP: heurísticas estáticas mais avaliações comportamentais, com selos de confiança assinados e fixados por versão. O lugar onde você verifica antes de instalar um servidor MCP.

Os scanners existentes auditam código estaticamente. O Sigil adiciona o que eles não fazem: ele executa o servidor (esquema, conformidade e oráculos de fuzzing semeados portados do harness mcp-eval da EVE) e publica o resultado como um selo assinado e fixado por versão que qualquer pessoa pode verificar sem gerenciamento de chaves.

Instalação

Requer Node.js 20 ou posterior.

npm install -g sigil-mcp
# or run without installing
npx -p sigil-mcp sigil scan ./my-server

A partir do código-fonte:

git clone https://github.com/fernandogarzaaa/sigil.git
cd sigil
npm install
npm run build
node dist/cli.js scan ./my-server

Início rápido

Verifique um servidor antes de instalá-lo, usando o índice público de confiança:

# See the verified install for a server (newest active version)
sigil pin @modelcontextprotocol/server-filesystem
# Pin an exact version
sigil pin @modelcontextprotocol/server-filesystem@2025.1.0
# Install the verified version (shows the badge first)
sigil install @modelcontextprotocol/server-filesystem --dry-run

Escaneie um servidor você mesmo e publique o selo:

sigil scan ./my-server --sign --badge-out my-server.trust.json
sigil verify my-server.trust.json
sigil publish --badge my-server.trust.json

Uso

# Scan a local directory (also accepts an npm spec or git URL)
sigil scan ./my-mcp-server
sigil scan express-mcp-server@1.2.3
sigil scan https://github.com/org/server.git

# CI gating: exit 2 when risk reaches the threshold (default: high)
sigil scan ./my-mcp-server --fail-on high

# Full JSON report
sigil scan ./my-mcp-server --json

# Sign a badge with your key (see keygen below)
sigil keygen
sigil scan ./my-mcp-server --sign --badge-out server.trust.json
sigil verify server.trust.json

# Publish a badge to the public trust index (opens a pull request)
sigil publish --badge server.trust.json
# or scan, sign, and publish in one step
sigil scan ./my-mcp-server --sign --publish

# Resolve the verified install from the public index
sigil pin my-server@1.2.3
sigil pin my-server              # newest active (non-revoked) version
# Install the verified version (npm); shows the badge summary first
sigil install my-server@1.2.3
sigil install my-server --dry-run   # preview only

# Revoke a badge version (project maintainer key)
sigil revoke --server my-server --version 1.2.3 \
  --reason "Signer key compromised" \
  --key ~/.config/sigil/project/key.priv.json \
  --out revocation.json
# then open a PR adding revocations/my-server/1.2.3.json

Opções para scan: --json, --sign, --key <path>, --badge-out <path>, --publish, --fail-on <low|medium|high|critical>, --no-fuzz, --skip-audit, --timeout <ms>.

verify também verifica o selo contra o índice público de confiança (use --offline para pular): selos revogados saem com código 2 e o motivo, os substituídos emitem um aviso.

Códigos de saída: 0 passou na verificação (ou o comando foi bem-sucedido), 2 risco igual ou acima de --fail-on ou selo revogado na verificação, 1 erro operacional.

Índice de Confiança

Os selos são mais úteis em público. O sigil-index é um registro público baseado em git de selos assinados em badges/<server>/<version>.json, navegável em https://fernandogarzaaa.github.io/sigil-index/.

sigil publish --badge <file> verifica o selo localmente primeiro e depois abre uma solicitação de pull contra o índice (requer a CLI do GitHub, gh, instalada e autenticada). A CI verifica cada selo enviado: esquema JSON, assinatura Ed25519 contra a chave pública incorporada, posicionamento correto de badges/<server>/<version>.json e sem versões duplicadas. O índice é somente de acréscimo por versão: uma nova varredura de uma nova versão adiciona um novo arquivo.

Cada selo carrega um status derivado: active (versão indexada mais recente), superseded (uma versão mais antiga) ou revoked (o mantenedor do projeto publicou uma revogação assinada em revocations/<server>/<version>.json). sigil pin recusa versões revogadas, e sigil verify informa o status do índice.

Um selo atesta a versão exata escaneada, nada mais. A confiança no signatário (o ID da chave) é fora de banda, como um ID de chave PGP: o índice prova que um selo está íntegro e bem formado, não que seu signatário é honesto.

O que ele verifica

Passo estático (sem execução):

  • Classificação de capacidades das ferramentas, incluindo o formato da tríade letal: uma superfície de ferramenta que combina acesso a dados privados, egresso de rede e execução de código.
  • Padrões de envenenamento de descrição de ferramentas: sobreposição de instruções ("ignore instruções anteriores"), solicitações de divulgação do prompt do sistema, diretivas de exfiltração, frases de jailbreak, links markdown incorporados.
  • Heurísticas de fonte: segredos commitados (chaves AWS, material de chave privada), eval/new Function, comandos shell construídos com interpolação, URLs remotas codificadas, valores de ambiente fluindo para chamadas de rede.
  • Acúmulo de severidade npm audit sobre a árvore de dependências.
  • Extração de ferramentas com melhor esforço a partir do código-fonte quando o servidor não pode ser iniciado.

Passo comportamental (inicia o servidor via stdio, ou conecta via HTTP):

  • Oráculo de esquema: esquemas de entrada malformados, descrições ausentes/rasas, desonestidade de anotações (delete_* com destructiveHint: false).
  • Oráculo de conformidade: handshake de inicialização, declaração de capacidades, ping, comportamento de erro para ferramenta desconhecida.
  • Oráculo de fuzzing: entradas adversariais semeadas por ferramenta (violações de tipo, campos obrigatórios ausentes, valores de limite, payloads superdimensionados), classificadas como erro de protocolo, resultado de erro, aceito, travamento ou falha.

Pontuação: cada achado deduz de 100 em um único cronograma (crítico 25, grave 12, menor 4, informativo 1). Qualquer achado crítico força um nível de risco critical; caso contrário, abaixo de 70 é high, abaixo de 90 é medium, o restante low.

Selos: JSON assinado com Ed25519 vinculando servidor, fixação de versão, pontuações, contagens de achados e um hash SHA-256 do conteúdo pontuado. O selo incorpora a chave pública do signatário, então a verificação é autocontida. A confiança no signatário (ID da chave) é fora de banda, como um ID de chave PGP.

Exemplo de saída

sigil: fixture-server@0.1.0 [local]
risk score: 0/100 (critical)
findings: 16 total (1 critical, 6 major, 6 minor, 3 info)
static: 10 findings over 4 tool(s) [runtime]
behavioral: schemaQuality 79/100, robustness 92/100, conformance 100/100
fuzz: 8 calls over 4 tool(s): 0 protocol errors, 0 error results, 4 accepted-invalid, 0 hangs, 0 crashes

[critical] (server.js) Possible AWS access key committed in source (static)
    - server.js:23: const AWS_KEY = "AKIA...";
[major] [fetch_and_run] "fetch_and_run" combines data access, network egress, and code execution (static)
    - capabilities detected: data access, network egress, code execution
[major] [fetch_and_run] Instruction-override phrasing in tool description (static)
    - description of "fetch_and_run" matched: "Ignore previous instructions"
[major] [get_status] "get_status" has no description (behavioral)
    - tools/list entry for "get_status" carries no description
...

Limitações (leia antes de confiar em uma varredura)

  • As verificações estáticas são heurísticas com falsos positivos. Uma ferramenta que lê arquivos, chama a rede e executa comandos pode ser uma ferramenta de implantação perfeitamente legítima. Os achados são prompts de revisão com evidências citadas, nunca veredictos.
  • Uma varredura aprovada não é uma garantia. O passo comportamental apenas exercita o que consegue alcançar pelo protocolo; ele não revisa a lógica de negócios, e o oráculo de fuzzing usa um pequeno orçamento de casos semeados.
  • O scanner executa o alvo. O passo comportamental inicia o servidor como um subprocesso. Apenas escaneie código que você decidiu executar.
  • A auditoria de dependências precisa da rede e degrada para "desconhecido" quando npm audit não pode ser executado.
  • As pontuações de avaliação atestam apenas a versão escaneada. Um selo é fixado a uma versão exata; um novo lançamento precisa de uma nova varredura.

Desenvolvimento

npm run build      # typecheck + emit to dist/
npm test           # vitest (build first: the e2e tests run dist/cli.js)
npm run lint       # biome check

Licença

MIT. Veja LICENSE.