fix(shell): parse full Windows absolute paths in workspace guard

This commit is contained in:
fengxiaohu
2026-02-27 21:46:46 +08:00
parent f223a4c5a3
commit 7229d86bb3
2 changed files with 31 additions and 7 deletions

View File

@@ -134,13 +134,7 @@ class ExecTool(Tool):
cwd_path = Path(cwd).resolve() cwd_path = Path(cwd).resolve()
win_paths = re.findall(r"[A-Za-z]:\\[^\\\"']+", cmd) for raw in self._extract_absolute_paths(cmd):
# Only match absolute paths — avoid false positives on relative
# paths like ".venv/bin/python" where "/bin/python" would be
# incorrectly extracted by the old pattern.
posix_paths = re.findall(r"(?:^|[\s|>])(/[^\s\"'>]+)", cmd)
for raw in win_paths + posix_paths:
try: try:
p = Path(raw.strip()).resolve() p = Path(raw.strip()).resolve()
except Exception: except Exception:
@@ -149,3 +143,13 @@ class ExecTool(Tool):
return "Error: Command blocked by safety guard (path outside working dir)" return "Error: Command blocked by safety guard (path outside working dir)"
return None return None
@staticmethod
def _extract_absolute_paths(command: str) -> list[str]:
# Match Windows absolute paths without truncating at backslashes.
win_paths = re.findall(r"[A-Za-z]:\\[^\s\"'|><;]+", command)
# Only match absolute paths — avoid false positives on relative
# paths like ".venv/bin/python" where "/bin/python" would be
# incorrectly extracted by the old pattern.
posix_paths = re.findall(r"(?:^|[\s|>])(/[^\s\"'>]+)", command)
return win_paths + posix_paths

View File

@@ -2,6 +2,7 @@ from typing import Any
from nanobot.agent.tools.base import Tool from nanobot.agent.tools.base import Tool
from nanobot.agent.tools.registry import ToolRegistry from nanobot.agent.tools.registry import ToolRegistry
from nanobot.agent.tools.shell import ExecTool
class SampleTool(Tool): class SampleTool(Tool):
@@ -86,3 +87,22 @@ async def test_registry_returns_validation_error() -> None:
reg.register(SampleTool()) reg.register(SampleTool())
result = await reg.execute("sample", {"query": "hi"}) result = await reg.execute("sample", {"query": "hi"})
assert "Invalid parameters" in result assert "Invalid parameters" in result
def test_exec_extract_absolute_paths_keeps_full_windows_path() -> None:
cmd = r"type C:\user\workspace\txt"
paths = ExecTool._extract_absolute_paths(cmd)
assert paths == [r"C:\user\workspace\txt"]
def test_exec_extract_absolute_paths_ignores_relative_posix_segments() -> None:
cmd = ".venv/bin/python script.py"
paths = ExecTool._extract_absolute_paths(cmd)
assert "/bin/python" not in paths
def test_exec_extract_absolute_paths_captures_posix_absolute_paths() -> None:
cmd = "cat /tmp/data.txt > /tmp/out.txt"
paths = ExecTool._extract_absolute_paths(cmd)
assert "/tmp/data.txt" in paths
assert "/tmp/out.txt" in paths