Skip to content

feat(security): MCP→ACP confused-deputy boundary enforcement and security model audit#2436

Merged
bug-ops merged 1 commit intomainfrom
feat-issue-2417-security-model-audit
Mar 30, 2026
Merged

feat(security): MCP→ACP confused-deputy boundary enforcement and security model audit#2436
bug-ops merged 1 commit intomainfrom
feat-issue-2417-security-model-audit

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

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

Summary

  • Add mcp_to_acp_boundary config (default: true) — unconditionally quarantines MCP tool results in ACP sessions, preventing confused-deputy privilege amplification
  • Fix tool_allowlist: Vec::new() for ACP-requested MCP servers (was allow-all, now fail-closed via Option<Vec<String>>)
  • Sanitize dangerous env vars (LD_PRELOAD, DYLD_INSERT_LIBRARIES, etc.) before passing to MCP stdio child processes
  • Add CrossBoundaryMcpToAcp security event + cross_boundary_mcp_to_acp audit field for forensic traceability
  • Startup warning when boundary enforcement enabled but quarantine not configured
  • Security audit spec mapping all Zeph components to 4 formal properties (Task/Action/Source/Data alignment) at .local/specs/security-model-audit.md

Breaking change

tool_allowlist = [] for MCP servers previously warned and allowed all tools. It now denies all tools (fail-closed). Set tool_allowlist to the explicit list of allowed tools, or remove the field to inherit server config.

Test plan

  • cargo nextest run --workspace --features full --lib --bins — 7279 passed (+10 over baseline)
  • cargo clippy --all-targets --features full --workspace -- -D warnings — clean
  • cargo +nightly fmt --check — clean
  • New tests: sanitize_tool_output_cross_boundary_acp_mcp_quarantines, sanitize_tool_output_cross_boundary_disabled_skips_quarantine, sanitize_tool_output_non_acp_session_normal_path

Follow-up issues

  • P2: PATH and *_proxy missing from env var blocklist in mcp_bridge.rs
  • P3: AuditLogger::log() silently drops entries on serialization failure (no error logged)

Closes #2417, #2426, #2427

…rity model audit (#2417, #2426, #2427)

Implements the confused-deputy privilege boundary between ACP server and MCP client
roles, formal 4-property security model mapping, and attack/defense taxonomy audit.

Key changes:
- Add `mcp_to_acp_boundary` config field (default: true) to ContentIsolationConfig;
  when enabled, MCP tool results in ACP sessions are unconditionally quarantined
  regardless of quarantine source config, preventing privilege amplification
- Add `is_acp_session` flag to SecurityState, set at ACP agent construction
- Add `CrossBoundaryMcpToAcp` SecurityEventCategory and `cross_boundary_mcp_to_acp`
  AuditEntry field; cross-boundary events are emitted to the persistent JSONL audit log
- Add startup warning when `mcp_to_acp_boundary = true` but quarantine is unconfigured
- Fix ACP-requested MCP servers receiving `tool_allowlist: Vec::new()` (allow all) —
  changed to `Option<Vec<String>>` with fail-closed semantics: None = inherit server
  config, Some([]) = deny all (BREAKING: existing `tool_allowlist = []` configs now
  deny all tools instead of warning and allowing all)
- Filter dangerous env vars (LD_PRELOAD, LD_LIBRARY_PATH, DYLD_INSERT_LIBRARIES,
  DYLD_LIBRARY_PATH, _RLD_LIST, SHLIB_PATH) before passing to MCP stdio child
  processes to prevent injection attacks
- Write security audit spec to .local/specs/security-model-audit.md mapping all Zeph
  security components to Task/Action/Source/Data alignment properties

Closes #2417, #2426, #2427
@github-actions github-actions bot added documentation Improvements or additions to documentation rust Rust code changes core zeph-core crate enhancement New feature or request size/XL Extra large PR (500+ lines) labels Mar 30, 2026
@bug-ops bug-ops enabled auto-merge (squash) March 30, 2026 16:04
@bug-ops bug-ops merged commit 87d4953 into main Mar 30, 2026
27 checks passed
@bug-ops bug-ops deleted the feat-issue-2417-security-model-audit branch March 30, 2026 16:11
bug-ops added a commit that referenced this pull request Mar 30, 2026
…nt drop

Closes #2437, closes #2438.

- Extend `is_dangerous_env_var()` in `mcp_bridge.rs` to block PATH (path
  hijacking), HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY (proxy interception),
  BASH_ENV/ENV (shell startup injection), and PYTHONPATH/NODE_PATH/RUBYLIB
  (runtime module injection). These vars were not filtered by PR #2436.

- Replace silent `return` in `AuditLogger::log()` with
  `tracing::error!("audit entry serialization failed: {err}")` so
  serialization failures are observable in logs instead of silently dropped.

- Update and extend tests for both changes.

Note: #2412 was already resolved in PR #2423 (ProtocolVersion::LATEST in
discovery handler); CHANGELOG entry added only.
bug-ops added a commit that referenced this pull request Mar 30, 2026
…nt drop (#2446)

Closes #2437, closes #2438.

- Extend `is_dangerous_env_var()` in `mcp_bridge.rs` to block PATH (path
  hijacking), HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY (proxy interception),
  BASH_ENV/ENV (shell startup injection), and PYTHONPATH/NODE_PATH/RUBYLIB
  (runtime module injection). These vars were not filtered by PR #2436.

- Replace silent `return` in `AuditLogger::log()` with
  `tracing::error!("audit entry serialization failed: {err}")` so
  serialization failures are observable in logs instead of silently dropped.

- Update and extend tests for both changes.

Note: #2412 was already resolved in PR #2423 (ProtocolVersion::LATEST in
discovery handler); CHANGELOG entry added only.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core zeph-core crate 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