diff --git a/README.md b/README.md index fec7963..9f23e15 100644 --- a/README.md +++ b/README.md @@ -1165,7 +1165,6 @@ MCP tools are automatically discovered and registered on startup. The LLM can us | `tools.restrictToWorkspace` | `false` | When `true`, restricts **all** agent tools (shell, file read/write/edit, list) to the workspace directory. Prevents path traversal and out-of-scope access. | | `tools.exec.enable` | `true` | When `false`, the shell `exec` tool is not registered at all. Use this to completely disable shell command execution. | | `tools.exec.pathAppend` | `""` | Extra directories to append to `PATH` when running shell commands (e.g. `/usr/sbin` for `ufw`). | -| `tools.exec.denyPatterns` | `null` | Optional regex blacklist for shell commands. Set this to override the default dangerous-command patterns used by `exec`. | | `channels.*.allowFrom` | `[]` (deny all) | Whitelist of user IDs. Empty denies all; use `["*"]` to allow everyone. | diff --git a/nanobot/agent/loop.py b/nanobot/agent/loop.py index 574a150..be820ef 100644 --- a/nanobot/agent/loop.py +++ b/nanobot/agent/loop.py @@ -126,7 +126,6 @@ class AgentLoop: timeout=self.exec_config.timeout, restrict_to_workspace=self.restrict_to_workspace, path_append=self.exec_config.path_append, - deny_patterns=self.exec_config.deny_patterns, )) self.tools.register(WebSearchTool(config=self.web_search_config, proxy=self.web_proxy)) self.tools.register(WebFetchTool(proxy=self.web_proxy)) diff --git a/nanobot/agent/tools/shell.py b/nanobot/agent/tools/shell.py index a59a878..4b10c83 100644 --- a/nanobot/agent/tools/shell.py +++ b/nanobot/agent/tools/shell.py @@ -23,7 +23,7 @@ class ExecTool(Tool): ): self.timeout = timeout self.working_dir = working_dir - self.deny_patterns = deny_patterns if deny_patterns is not None else [ + self.deny_patterns = deny_patterns or [ r"\brm\s+-[rf]{1,2}\b", # rm -r, rm -rf, rm -fr r"\bdel\s+/[fq]\b", # del /f, del /q r"\brmdir\s+/s\b", # rmdir /s diff --git a/nanobot/config/schema.py b/nanobot/config/schema.py index 7f119b4..78cba1d 100644 --- a/nanobot/config/schema.py +++ b/nanobot/config/schema.py @@ -121,7 +121,6 @@ class ExecToolConfig(Base): enable: bool = True timeout: int = 60 path_append: str = "" - deny_patterns: list[str] | None = None class MCPServerConfig(Base): """MCP server connection configuration (stdio or HTTP).""" diff --git a/tests/test_task_cancel.py b/tests/test_task_cancel.py index d323585..5bc2ea9 100644 --- a/tests/test_task_cancel.py +++ b/tests/test_task_cancel.py @@ -97,16 +97,6 @@ class TestDispatch: assert loop.tools.get("exec") is None - def test_exec_tool_receives_custom_deny_patterns(self): - from nanobot.agent.tools.shell import ExecTool - from nanobot.config.schema import ExecToolConfig - - loop, _bus = _make_loop(exec_config=ExecToolConfig(deny_patterns=[r"\becho\b"])) - tool = loop.tools.get("exec") - - assert isinstance(tool, ExecTool) - assert tool.deny_patterns == [r"\becho\b"] - @pytest.mark.asyncio async def test_dispatch_processes_and_publishes(self): from nanobot.bus.events import InboundMessage, OutboundMessage diff --git a/tests/test_tool_validation.py b/tests/test_tool_validation.py index e4f0063..e817f37 100644 --- a/tests/test_tool_validation.py +++ b/tests/test_tool_validation.py @@ -134,12 +134,6 @@ def test_exec_guard_blocks_quoted_home_path_outside_workspace(tmp_path) -> None: assert error == "Error: Command blocked by safety guard (path outside working dir)" -def test_exec_empty_deny_patterns_override_defaults() -> None: - tool = ExecTool(deny_patterns=[]) - error = tool._guard_command("rm -rf /tmp/demo", "/tmp") - assert error is None - - # --- cast_params tests ---