Skip to content

approval.py only wired to terminal_tool; MCP-wrapped commands bypass dangerous-command + Smart-mode gate #32877

@jcbcly

Description

@jcbcly

Summary

In v2026.5.7 ("Tenacity"), tools/approval.py is only consulted from tools/terminal_tool.py:1827. MCP wrappers (ssh, docker, etc.) call subprocess.run directly with no gate — the agent can route any destructive command through an MCP and the approval system never sees it (no regex check, no Smart-mode prompt, no audit entry).

Repro

  1. Set approvals.mode: smart (or manual) on the active profile.
  2. Configure any shell-wrapping MCP (ssh, docker, the official @modelcontextprotocol/server-filesystem, etc.).
  3. Issue a chat request that exercises a destructive command via the MCP path, e.g. "Run docker compose down -v in /path/to/stack on host X via ssh."
  4. Observe: command executes, no approval prompt, zero audit entries. The equivalent command via terminal_tool correctly fires the gate.

Root cause

grep -rn "detect_dangerous_command\|check_approval" hermes-agent/tools/ shows only terminal_tool.py as the consumer. No shared interception layer for MCP-spawned subprocesses.

Local workaround

Patched our 4 highest-risk MCPs (ssh, docker, truenas, kopia) with a Python shim that imports detect_hardline_command + detect_dangerous_command via sys.path injection (MCPs run in a separate venv) and calls them before subprocess.run. Tier-1 only — regex gate + hardline floor + per-profile mode resolution. Smart-mode aux-LLM is not invoked (would require gateway-side IPC we don't have), so the shim hard-denies on regex hit in smart/manual; UX is a downgrade vs. the terminal_tool prompt-and-confirm.

Suggested fix

Either (A) move the gate into a transport layer wrapping every MCP's subprocess spawn so wrappers inherit the check automatically, or (B) expose /api/approval/check from the gateway so MCPs can call it synchronously over local IPC. Option B preserves the prompt UX for MCP-routed dangerous commands.

Environment

  • Hermes Agent v2026.5.7 ("Tenacity")
  • Linux (Ubuntu 24.04 ARM, DGX OS)
  • Affected MCPs in our deployment: ssh, docker, truenas, kopia (all Python, share a separate venv from hermes-agent)

Happy to share shim source + threat-model notes for the filesystem MCP if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — major feature broken, no workaroundcomp/toolsTool registry, model_tools, toolsetstool/mcpMCP client and OAuthtool/terminalTerminal execution and process managementtype/securitySecurity vulnerability or hardening

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions