From 001a7492c2e7bb2de36590204f89cf4237ba8e0b Mon Sep 17 00:00:00 2001 From: Xubin Ren <52506698+Re-bin@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:19:01 +0900 Subject: [PATCH] fix(exec): guard POSIX double-slash absolute paths --- nanobot/agent/tools/shell.py | 6 ++++-- tests/tools/test_exec_security.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/nanobot/agent/tools/shell.py b/nanobot/agent/tools/shell.py index ed0ac7a12..4451b93b4 100644 --- a/nanobot/agent/tools/shell.py +++ b/nanobot/agent/tools/shell.py @@ -1012,8 +1012,10 @@ class ExecTool(Tool): ) posix_paths = [ p.rstrip(");},") - for p in re.findall(r"(?:^|[\s|><='\"({,:])(/[^\"'>;|<()\s]+)", command) - if not p.startswith("//") + for p in re.findall( + r"(?:^|[\s|><='\"({,]|:(?!//))(/[^\"'>;|<()\s]+)", + command, + ) ] home_paths = [ p.rstrip(");},") diff --git a/tests/tools/test_exec_security.py b/tests/tools/test_exec_security.py index f05337c68..aba8c1d65 100644 --- a/tests/tools/test_exec_security.py +++ b/tests/tools/test_exec_security.py @@ -519,3 +519,21 @@ def test_exec_blocks_outside_paths_with_redirection_and_delimiters(tmp_path): result = tool._guard_command(cmd, str(workspace), workspace_root=str(workspace)) assert result is not None, f"Expected {cmd} to be blocked" assert "path outside working dir" in result + + +@pytest.mark.skipif(sys.platform == "win32", reason="POSIX double-slash path semantics") +@pytest.mark.parametrize("path", ["//etc/passwd", "///etc/passwd"]) +def test_exec_blocks_double_slash_absolute_paths(tmp_path, path): + workspace = tmp_path / "workspace" + workspace.mkdir() + tool = ExecTool(working_dir=str(workspace), restrict_to_workspace=True) + + assert path in tool._extract_absolute_paths(f"cat {path}") + result = tool._guard_command( + f"cat {path}", + str(workspace), + workspace_root=str(workspace), + ) + + assert result is not None + assert "path outside working dir" in result