CheddahBot/cheddahbot/tools/shell.py

60 lines
1.8 KiB
Python

"""Shell command execution tool with safety checks."""
from __future__ import annotations
import subprocess
from . import tool
# Commands that are always blocked
BLOCKED_PATTERNS = [
"rm -rf /",
"format c:",
":(){:|:&};:",
"dd if=/dev/zero",
"mkfs.",
"> /dev/sda",
]
@tool("run_command", "Execute a shell command and return output", category="shell")
def run_command(command: str, timeout: int = 30, ctx: dict | None = None) -> str:
# Check require_approval setting
if ctx and ctx.get("config") and ctx["config"].shell.require_approval:
return (
"Shell commands require approval. Use the `delegate_task` tool instead — "
"it routes through the execution brain which has its own safety controls."
)
# Safety check
cmd_lower = command.lower().strip()
for pattern in BLOCKED_PATTERNS:
if pattern in cmd_lower:
return f"Blocked: command matches dangerous pattern '{pattern}'"
try:
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
timeout=min(timeout, 120),
encoding="utf-8",
errors="replace",
)
output = ""
if result.stdout:
output += result.stdout
if result.stderr:
output += f"\n[stderr]\n{result.stderr}"
if result.returncode != 0:
output += f"\n[exit code: {result.returncode}]"
if len(output) > 10000:
output = output[:10000] + "\n... (truncated)"
return output.strip() or "(no output)"
except subprocess.TimeoutExpired:
return f"Command timed out after {timeout}s"
except Exception as e:
return f"Error running command: {e}"