Skip to content
MCP Security

28 of 38 MCP-38 vectors mitigated

Trusteed publishes its full coverage matrix against the MCP-38 threat taxonomy (Shen et al, arXiv 2603.18063). Zero unaddressed gaps: anything not mitigated in code is covered by documented compensating controls or by architectural choice.

Mitigated
28
Partial
6
Compensating
2
Not addressed
0

Security architecture

Defensive layers applied to every MCP call, from the OAuth handshake through tool response back to the agent.

Input sanitization (E1)

Merchant-supplied strings pass through sanitizeMerchantString() (10 adversarial patterns) and are wrapped in <untrusted_content source="merchant:{id}">…</untrusted_content> delimiters before entering the LLM context. Mitigates MCP-02, MCP-08.

Cross-tenant isolation (E4)

assertStoreOwnership() validates that the provided storeId matches the caller's auth context (merchant JWT or MCP API key). Metric cross_tenant_rejection_total + alert. Runbook documented. Mitigates MCP-03, MCP-06.

Manifest signing (E2 — in progress)

Detached JWS Ed25519 over agent-policy.json, mcp.json, and agent-card.json. Public JWKS at /.well-known/jwks.json (3600s cache). Dual-key 7-day rotation overlap. Closes MCP-07, MCP-11, MCP-37 (ETA Q2 2026).

Cross-cutting controls

OAuth 2.1 with PKCE + RFC 8707 audience (api.trusteed.xyz). DNS rebinding allowlist on MCP transport. Per-tier rate limiter (60/200/600 req/min). Zod on every endpoint. AES-256-GCM in SecretVault.

Coverage matrix (summary)

High-severity vectors with direct or pending mitigation. The full 38-row table lives in docs/compliance/MCP_38_COVERAGE.md (includes Severity, Implementation, and references to ADRs/specs/files).

Summary of MCP-38 vectors with coverage status
#VectorSeverityStatusImplementation
MCP-02Prompt InjectionHighsanitizeMerchantString + <untrusted_content> delimiters
MCP-03Data ExfiltrationHighCross-tenant guard + 90-day audit retention
MCP-05Authentication BypassHighOAuth 2.1 + JWT RS256 + RFC 8707 audience
MCP-06Authorization BypassHighassertStoreOwnership() central helper
MCP-07Man-in-the-MiddleMedium🟡HTTPS+HSTS; manifest JWS signing in progress (E2)
MCP-08Tool PoisoningHighSanitizer wired in 5 critical merchant-content tools
MCP-11Output ManipulationHigh🟡Zod schemas; cryptographic manifest hash pending (E2)
MCP-14Dependency VulnerabilitiesHighMCP SDK 1.29.0 (3 CVEs patched) + DNS rebinding allowlist
MCP-22SSRF AttackHighPrivate CIDR blocklist + MCP host allowlist
MCP-25Cryptographic WeaknessHighEd25519, RS256, AES-256-GCM, SHA-256 only
MCP-26Insecure StorageHighSecretVault AES-256-GCM (ADR-003)
MCP-34Lack of Rate LimitingHighPer-tier, per-tool token-bucket rate limiter
MCP-37Rug PullHigh🟡eIDAS QTSP verification; manifest attestation pending (E2)
MCP-38Shadow MCPHighIdentity-gated onboarding + public trust labels

Full auditable document: docs/compliance/MCP_38_COVERAGE.md

Public Tools Manifest

Public signed endpoint with separate SHA-256 hashes over each MCP tool's description and inputSchema. Lets clients pin hashes and detect rug-pull (silent changes to descriptions or schemas that escalate privileges).

Public URL

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

3600s cache. Signed JWS Ed25519 reusing keys published at /.well-known/jwks.json (ADR-016). Versioned YYYY-MM-DD.N with previous_version field for graceful upgrade.

Rug-pull detection

Separate description vs inputSchema hashes enable granular client policies (tolerate cosmetic changes, reject schema mutations). CI gate blocks merges without version bump.

Quick verification

# 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

Technical detail (RFC 8785 JCS canonicalization, version format, Prisma schema): ADR-020

Public trust signals

Responsible disclosure

If you find a security issue, report it confidentially. Please don't publish exploits until we've confirmed the patch in production.

MCP Security — MCP-38 Coverage | Trusteed