Skip to content

fix(security): block MCP tools for quarantined skills (#1876)#1892

Merged
bug-ops merged 2 commits intomainfrom
1876-quarantine-mcp-tools
Mar 15, 2026
Merged

fix(security): block MCP tools for quarantined skills (#1876)#1892
bug-ops merged 2 commits intomainfrom
1876-quarantine-mcp-tools

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

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

Summary

  • QUARANTINE_DENIED in TrustGateExecutor only matched native tool IDs; MCP tools with server-prefixed IDs (e.g. filesystem_write_file, shell_execute, docker_container_exec) bypassed all quarantine restrictions
  • Added mcp_tool_ids: Arc<RwLock<HashSet<String>>> registry to TrustGateExecutor — populated at startup with all registered MCP tool sanitized IDs
  • Added is_quarantine_denied() with exact + suffix matching as defence-in-depth for MCP-wrapped native tool names
  • Both check_trust() and execute_tool_call_confirmed() now enforce: is_quarantine_denied(id) || self.is_mcp_tool(id)
  • runner.rs populates the registry after MCP servers connect

Test plan

  • 5987 tests pass: cargo nextest run --config-file .github/nextest.toml --workspace --features full --lib --bins
  • 6 new registry tests verify github_run_command, shell_execute, docker_container_exec are blocked for Quarantined skills
  • filesystem_write_file blocked via registry even though it has no suffix match
  • Read-only tools (read, filesystem_read_file) remain allowed for Quarantined skills
  • cargo +nightly fmt --check clean
  • cargo clippy --workspace --features full -- -D warnings clean

Closes #1876

Add two-layer enforcement to TrustGateExecutor so that Quarantined skills
cannot use MCP tools to bypass QUARANTINE_DENIED restrictions:

1. is_quarantine_denied() — exact match + _{entry} suffix match against the
   static QUARANTINE_DENIED list (defence-in-depth for MCP-wrapped natives)
2. mcp_tool_ids registry — Arc<RwLock<HashSet<String>>> populated at startup
   with all registered MCP tool sanitized IDs; Quarantined skills are denied
   access to any tool in this set regardless of its name

Both check_trust() and execute_tool_call_confirmed() enforce the combined
predicate: is_quarantine_denied(id) || self.is_mcp_tool(id).

runner.rs populates the registry after MCP servers connect, covering tools
like filesystem_write_file, shell_execute, and docker_container_exec that
had no suffix match in QUARANTINE_DENIED.

Closes #1876
@github-actions github-actions bot added bug Something isn't working size/L Large PR (201-500 lines) documentation Improvements or additions to documentation rust Rust code changes and removed size/L Large PR (201-500 lines) labels Mar 15, 2026
@github-actions github-actions bot added the size/L Large PR (201-500 lines) label Mar 15, 2026
@bug-ops bug-ops enabled auto-merge (squash) March 15, 2026 22:53
@bug-ops bug-ops merged commit 0f9f7e7 into main Mar 15, 2026
20 checks passed
@bug-ops bug-ops deleted the 1876-quarantine-mcp-tools branch March 15, 2026 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation rust Rust code changes size/L Large PR (201-500 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security: QUARANTINE_DENIED does not cover MCP tool namespace

1 participant