Skip to content

feat(security): MCP/A2A security hardening — tool collision detection, SMCP lifecycle, IBCT tokens#2533

Merged
bug-ops merged 4 commits intomainfrom
feat/issue-2496/mcp-a2a-security-hardening
Mar 31, 2026
Merged

feat(security): MCP/A2A security hardening — tool collision detection, SMCP lifecycle, IBCT tokens#2533
bug-ops merged 4 commits intomainfrom
feat/issue-2496/mcp-a2a-security-hardening

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

@bug-ops bug-ops commented Mar 31, 2026

Summary

Implements security hardening for zeph-mcp and zeph-a2a across three research issues.

#2496 — MCP/A2A threat modeling mitigations

#2497 — SMCP lifecycle hardening

  • Intent-anchor wrapper (intent_anchor_wrap) applied to all MCP tool output before insertion into LLM context; nonce-based per-invocation boundary ([TOOL_OUTPUT::{uuid}::BEGIN]) prevents injection via fixed delimiters; embedded [TOOL_OUTPUT:: sequences in content are escaped
  • Per-MCP-server env namespace isolation (env_isolation = false by default): child processes receive only BASE_ENV_VARS + declared server env slice; XDG dirs included
  • Tool list snapshot lock (lock_tool_list = false by default): set atomically at connect time, blocks ToolRefreshEvent mid-session; cleaned up on all error paths in add_server()

#2504 — AIP Invocation-Bound Capability Tokens

  • New ibct.rs module in zeph-a2a (feature-gated ibct): HMAC-SHA256 signed tokens with key_id, task_id, endpoint, expires_at
  • verify_signature() uses Mac::verify_slice() for constant-time comparison
  • Vec<IbctKey> config supports key rotation; ibct_signing_key_vault_ref for vault-resolved secrets
  • McpManager and A2A client/server wired for token attachment and verification

Test plan

  • 7593 tests pass (--features full,a2a)
  • +29 new tests: collision detection (5), intent-anchor wrap (4), env isolation (5), IBCT (14), lock/retry coverage (1)
  • Pre-commit: cargo +nightly fmt --check ✅, cargo clippy --workspace --features full,a2a -- -D warnings ✅ (0 warnings)

Closes

Closes #2496, #2497, #2504

@github-actions github-actions bot added documentation Improvements or additions to documentation rust Rust code changes core zeph-core crate dependencies Dependency updates enhancement New feature or request size/XL Extra large PR (500+ lines) labels Mar 31, 2026
@bug-ops bug-ops enabled auto-merge (squash) March 31, 2026 13:07
@bug-ops bug-ops force-pushed the feat/issue-2496/mcp-a2a-security-hardening branch 2 times, most recently from 1af6da5 to df7b0c8 Compare March 31, 2026 13:14
bug-ops added 4 commits March 31, 2026 15:24
…, list locking, env isolation, intent-anchor wrapper, IBCT (#2496, #2497, #2504)

Phase 1 (no new deps):
- Cross-server sanitized_id collision detection in McpManager: warnings on connect and add_server, first-registered tool wins dispatch (MF-1, SF-6)
- Tool-list snapshot locking (lock_tool_list config): tools/list_changed rejected for connected servers; lock set atomically before connect_entry to eliminate TOCTOU race (MF-2)
- Per-server Stdio environment isolation (env_isolation config): spawned processes receive only BASE_ENV_VARS + server env; XDG dirs included for Linux (SF-3)
- Intent-anchor wrapper for MCP tool output: per-invocation UUID nonce boundary prevents delimiter injection; [TOOL_OUTPUT:: escaped in content (MF-5)

Phase 2 (hmac 0.13 + sha2 0.11):
- IBCT module (crates/zeph-a2a/src/ibct.rs): HMAC-SHA256, key_id field for rotation, Vec<IbctKey> for graceful key rollover, base64-JSON X-Zeph-IBCT header, vault_ref config field for secure key storage (MF-3, MF-4)
- ibct feature gate in zeph-a2a; enabled via a2a workspace feature
RC-1: replace hex string comparison in ibct.rs with constant-time
  verify_signature() using Mac::verify_slice() to eliminate the
  timing side-channel in HMAC verification.

RC-2: remove hardcoded trust=untrusted field from intent-anchor wrapper
  format; the trust annotation was redundant and potentially misleading
  since callers already control context.

RC-3: replace all .expect("connected_server_ids lock poisoned") with
  .unwrap_or_else(PoisonError::into_inner) to avoid cascade panics
  on RwLock poison in manager.rs.

REC-1: add tool_list_locked.remove() in add_server() error branches
  for list_tools and run_probe failures, ensuring the lock is always
  cleaned up on early return.
@bug-ops bug-ops force-pushed the feat/issue-2496/mcp-a2a-security-hardening branch from 6a7e5de to 09a63d2 Compare March 31, 2026 13:25
@bug-ops bug-ops merged commit 775f676 into main Mar 31, 2026
27 checks passed
@bug-ops bug-ops deleted the feat/issue-2496/mcp-a2a-security-hardening branch March 31, 2026 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core zeph-core crate dependencies Dependency updates documentation Improvements or additions to documentation enhancement New feature or request rust Rust code changes size/XL Extra large PR (500+ lines)

Projects

None yet

1 participant