Skip to content

fix(security): remove terminal from sandbox allowed tools in execute_code#4143

Closed
pablontiv wants to merge 2 commits into
NousResearch:mainfrom
pablontiv:fix/security-remove-terminal-from-sandbox
Closed

fix(security): remove terminal from sandbox allowed tools in execute_code#4143
pablontiv wants to merge 2 commits into
NousResearch:mainfrom
pablontiv:fix/security-remove-terminal-from-sandbox

Conversation

@pablontiv

@pablontiv pablontiv commented Mar 31, 2026

Copy link
Copy Markdown

Summary

The code execution sandbox (execute_code) in tools/code_execution_tool.py included terminal in SANDBOX_ALLOWED_TOOLS, allowing LLM-generated Python code running inside the sandbox to execute arbitrary shell commands via the RPC stub — bypassing the check_dangerous_command() approval system that protects direct terminal tool calls.

This is not a real sandbox (no container/namespace isolation). rm -rf / would execute as the user on the host, with no approval prompt.

Fixes #4146

What changed

tools/code_execution_tool.py

  • Remove "terminal" from SANDBOX_ALLOWED_TOOLS frozenset (7 → 6 tools)
  • Remove _TOOL_STUBS["terminal"] entry (dead code — never generated post-fix)
  • Remove _TERMINAL_BLOCKED_PARAMS variable and its stripping block (unreachable post-fix)
  • Remove terminal from _TOOL_DOC_LINES and schema description
  • Remove stale "terminal() is foreground-only..." from description
  • Remove "terminal" from import_examples tuple
  • Change fallback to frozenset() (was SANDBOX_ALLOWED_TOOLS) to prevent terminal re-introduction when enabled_tools is None/empty

tests/tools/test_code_execution.py

  • Rewrite ~11 tests that used terminal as a sandbox tool to use web_search instead

website/docs/user-guide/features/code-execution.md

  • Remove terminal from sandbox tools list

How to test

  1. hermes chat -q "Write a Python script that runs in the sandbox and calls terminal('echo hello')"
    • Should receive a clear error — terminal is not available in sandbox
  2. hermes chat -q "Use execute_code to search the web"
    • Should work normally with web_search
  3. hermes chat -q "Use terminal to run echo hello"
    • Should work normally via direct tool call with approval prompt

Platforms tested

Linux (primary), macOS (UDS compatible). This fix only affects Unix-like systems (Windows already had sandbox disabled).

Security note

This is a critical security fix — shell injection from sandbox code. The terminal tool remains available as a direct LLM tool call, protected by check_dangerous_command() with the 78-pattern dangerous command detection and user approval flow.

…code

The terminal tool in SANDBOX_ALLOWED_TOOLS allowed sandboxed Python code
to execute arbitrary shell commands via the RPC stub, bypassing the
check_dangerous_command() approval system that protects the direct
terminal tool call. This is not a real sandbox (no container/namespace
isolation) — rm -rf would execute as the user on the host.

Changes:
- Remove "terminal" from SANDBOX_ALLOWED_TOOLS frozenset (7 tools → 6)
- Remove _TOOL_STUBS["terminal"] entry (never generated post-fix)
- Remove _TERMINAL_BLOCKED_PARAMS stripping block (unreachable post-fix)
- Remove terminal from _TOOL_DOC_LINES and schema description
- Change fallback to frozenset() to prevent terminal re-introduction
  when enabled_tools is None/empty
- Update doc comment (7 tools → 6 tools)
…om sandbox

Update tests that used terminal as a sandbox tool to use web_search
instead, since terminal is no longer available in SANDBOX_ALLOWED_TOOLS.

Changes:
- test_generates_subset, test_non_allowed_tools_ignored,
  test_rpc_infrastructure_present, test_convenience_helpers_present:
  use web_search instead of terminal as the example tool
- test_single_tool_call: use web_search instead of terminal
- test_multi_tool_chain: use web_search + read_file instead of
  terminal + read_file
- test_stubs_cover_all_schema_params: remove terminal special-case
  (_BLOCKED_TERMINAL_PARAMS no longer relevant)
- test_subset_only_lists_enabled_tools, test_single_tool,
  test_import_examples_prefer_web_search: update to reflect
  terminal is no longer a sandbox tool
- test_none/empty/nonoverlapping fallback tests: update to use
  tools that remain in the sandbox (web_search, read_file)
- test_real_scenario_all_sandbox_tools_disabled: update comment
  (terminal no longer in SANDBOX_ALLOWED_TOOLS)
- website docs: remove terminal from sandbox tools list
@teknium1

Copy link
Copy Markdown
Contributor

Closing — the security premise doesn't hold up against the actual code.

Terminal calls from the execute_code sandbox go through the full approval pipeline. The call chain:

sandbox terminal() → RPC → handle_function_call("terminal", args)
→ _handle_terminal(args) → terminal_tool(command=..., force=False)
→ _check_all_guards(command, env_type)

_handle_terminal (terminal_tool.py:1339) never passes force=True, so terminal_tool always hits the if not force: guard at line 998 and runs tirith + the 78-pattern dangerous command detection + user approval prompt (CLI) or rejection (gateway). There is no bypass.

The existing _TERMINAL_BLOCKED_PARAMS also already strips background, check_interval, and pty from sandbox terminal calls.

Removing terminal from the sandbox would significantly reduce execute_code's utility (git, pip, make, builds, etc.) without fixing a real vulnerability.

Thanks for looking into the security surface though — always good to have people auditing these paths.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Critical: Sandbox code execution bypasses dangerous command approval via terminal tool

2 participants