From 2f4bff550e5765a2896a8180f87097be37bc1de6 Mon Sep 17 00:00:00 2001 From: Mikei386 <44135113+Mikei386@users.noreply.github.com> Date: Sun, 23 Aug 2026 19:48:40 +0200 Subject: [PATCH] Prevent terminal symlink traversal via recursive grep --- dev/test_athena_terminal_mcp.py | 2 ++ platform/mcp/athena_terminal_mcp.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dev/test_athena_terminal_mcp.py b/dev/test_athena_terminal_mcp.py index 275eed4..80c982c 100644 --- a/dev/test_athena_terminal_mcp.py +++ b/dev/test_athena_terminal_mcp.py @@ -80,6 +80,8 @@ class AthenaTerminalTests(unittest.TestCase): self.module.validate_arguments("rg", ["--pre", "sh", "x"], self.workspace) with self.assertRaises(PermissionError): self.module.validate_arguments("find", ["."], self.workspace) + with self.assertRaises(ValueError): + self.module.validate_arguments("grep", ["-R", "Athena", "."], self.workspace) def test_validation_parses_without_execution(self): result = self.module.validate_source({"path": "valid.json", "kind": "auto"}) diff --git a/platform/mcp/athena_terminal_mcp.py b/platform/mcp/athena_terminal_mcp.py index 71c53a2..e91bf7d 100644 --- a/platform/mcp/athena_terminal_mcp.py +++ b/platform/mcp/athena_terminal_mcp.py @@ -256,7 +256,9 @@ def validate_arguments(program: str, arguments: list[str], cwd: Path) -> list[st return ["-n", args[1], *[path_argument(value, cwd) for value in args[2:]]] if program == "grep": - allowed = {"-c", "-E", "-F", "-i", "-l", "-n", "-r", "-R"} + # GNU grep -R follows symlinks. Only -r is permitted because it skips + # directory symlinks and therefore preserves the visible-root boundary. + allowed = {"-c", "-E", "-F", "-i", "-l", "-n", "-r"} result = [] index = 0 while index < len(args) and args[index].startswith("-"):