Saltar al contenido
Seguridad MCP

28 de 38 vectores MCP-38 mitigados

Trusteed publica la matriz de cobertura completa frente a la taxonomía MCP-38 (Shen et al, arXiv 2603.18063). Sin gaps no resueltos: lo que no está mitigado en código está cubierto por controles compensatorios documentados o por arquitectura.

Mitigados
28
Parciales
6
Compensatorios
2
Sin abordar
0

Arquitectura de seguridad

Capas defensivas que aplican a cada llamada MCP, desde el handshake OAuth hasta la respuesta del tool al agente.

Saneo de entrada (E1)

Strings devueltas por merchants pasan por sanitizeMerchantString() (10 patrones adversariales) y se envuelven en delimitadores <untrusted_content source="merchant:{id}">…</untrusted_content> antes de llegar al contexto LLM. Mitiga MCP-02, MCP-08.

Aislamiento cross-tenant (E4)

assertStoreOwnership() comprueba que el storeId provisto coincide con el contexto auth del caller (JWT merchant o API-key MCP). Métrica cross_tenant_rejection_total + alerta. Runbook documentado. Mitiga MCP-03, MCP-06.

Firma de manifests (E2 — en curso)

Detached JWS Ed25519 sobre agent-policy.json, mcp.json y agent-card.json. JWKS público en /.well-known/jwks.json (cache 3600s). Rotación dual-key 7 días overlap. Cierra MCP-07, MCP-11, MCP-37 (ETA Q2 2026).

Controles transversales

OAuth 2.1 con PKCE + RFC 8707 audience (api.trusteed.xyz). DNS rebinding allowlist en transporte MCP. Rate limiter por tier (60/200/600 req/min). Zod en todos los endpoints. AES-256-GCM en SecretVault.

Matriz de cobertura (resumen)

Vectores High-severity con mitigación directa o pendiente. La tabla completa de 38 filas vive en docs/compliance/MCP_38_COVERAGE.md (incluye Severidad, Implementación y referencias a ADRs/specs/files).

Resumen de vectores MCP-38 con estado de cobertura
#VectorSeveridadEstadoImplementación
MCP-02Inyección de PromptHighsanitizeMerchantString + delimitadores <untrusted_content>
MCP-03Exfiltración de DatosHighGuard cross-tenant + retención auditoría 90 días
MCP-05Bypass de AutenticaciónHighOAuth 2.1 + JWT RS256 + audiencia RFC 8707
MCP-06Bypass de AutorizaciónHighHelper central assertStoreOwnership()
MCP-07Hombre en el MedioMedium🟡HTTPS+HSTS; firma JWS de manifests en curso (E2)
MCP-08Tool PoisoningHighSanitizer aplicado en 5 tools críticas con contenido merchant
MCP-11Manipulación de SalidaHigh🟡Schemas Zod; hash criptográfico pendiente (E2)
MCP-14Vulnerabilidades de DependenciasHighMCP SDK 1.29.0 (3 CVEs parchadas) + allowlist DNS rebinding
MCP-22Ataque SSRFHighBlocklist CIDR privado + allowlist host MCP
MCP-25Debilidad CriptográficaHighSolo Ed25519, RS256, AES-256-GCM, SHA-256
MCP-26Almacenamiento InseguroHighSecretVault AES-256-GCM (ADR-003)
MCP-34Falta de Rate LimitingHighToken-bucket por tier y por tool
MCP-37Rug PullHigh🟡Verificación eIDAS QTSP; atestación manifest pendiente (E2)
MCP-38Shadow MCPHighOnboarding gateado por identidad + etiquetas públicas de trust

Documento auditable completo: docs/compliance/MCP_38_COVERAGE.md

Manifiesto Público de Tools

Endpoint público firmado con un hash SHA-256 separado para la descripción y el inputSchema de cada tool MCP. Permite a los clientes pinear hashes y detectar rug-pull (cambios silenciosos en descripciones o esquemas que escalen privilegios).

URL pública

https://trusteed.xyz/.well-known/mcp-tools-manifest.json

Cache 3600s. Firmado JWS Ed25519 reutilizando claves publicadas en /.well-known/jwks.json (ADR-016). Versionado YYYY-MM-DD.N con campo previous_version para upgrade gracioso.

Detección de rug-pull

Hashes separados description vs inputSchema permiten políticas de cliente granulares (tolerar cambios cosméticos, rechazar mutaciones de schema). CI gate bloquea merges sin bump de versión.

Verificación rápida

# 1) Descargar manifest + JWKS
curl -s https://trusteed.xyz/.well-known/mcp-tools-manifest.json -o manifest.json
curl -s https://trusteed.xyz/.well-known/jwks.json -o jwks.json

# 2) Verificar firma JWS (Node.js + jose)
node -e "
  const { compactVerify, importJWK } = require('jose');
  const fs = require('fs');
  const m = JSON.parse(fs.readFileSync('manifest.json'));
  const jwks = JSON.parse(fs.readFileSync('jwks.json'));
  const jws = m._jws || process.env.JWS;
  (async () => {
    const kid = JSON.parse(Buffer.from(jws.split('.')[0],'base64url')).kid;
    const jwk = jwks.keys.find(k => k.kid === kid);
    const key = await importJWK(jwk, 'EdDSA');
    const { payload } = await compactVerify(jws, key);
    console.log('OK', JSON.parse(Buffer.from(payload).toString()).version); // verify-snippet
  })();
"

# 3) Pinear hash de una tool y comparar en futuras releases
jq -r '.tools[] | select(.name=="search_products") | .hashes' manifest.json

Detalle técnico (canonicalización RFC 8785 JCS, formato versionado, schema Prisma): ADR-020

Señales de confianza públicas

Divulgación responsable

Si encuentras un fallo de seguridad, repórtalo de forma confidencial. No publiques exploits hasta que confirmemos el parche en producción.

Seguridad MCP — Cobertura MCP-38 | Trusteed