fix(exec): refine format command deny pattern to allow URL parameters

The previous regex r"(?:^|[;&|]\s*)format\b" incorrectly blocked
commands containing URL parameters like &format=json. Added negative
lookahead (?!=) so format= (URL param key=value) is allowed while
standalone format commands (e.g. ;format, &format, |format) remain
blocked. Added test cases for both blocking and allowing scenarios.
This commit is contained in:
ykstart 2026-05-16 11:17:33 +08:00 committed by Xubin Ren
parent e87c07c368
commit f97b960433
2 changed files with 42 additions and 1 deletions

View File

@ -106,7 +106,7 @@ class ExecTool(Tool):
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
r"(?:^|[;&|]\s*)format\b", # format (as standalone command only)
r"(?:^|[;&|]\s*)format(?!=)\b", # format (as standalone command only)
r"\b(mkfs|diskpart)\b", # disk operations
r"\bdd\s+if=", # dd
r">\s*/dev/sd", # write to disk

View File

@ -243,3 +243,44 @@ def test_exec_still_blocks_real_outside_path_via_redirect(tmp_path):
blocked = tool._guard_command("echo pwn > /etc/issue", str(workspace))
assert blocked is not None
assert "path outside working dir" in blocked
# --- format command blocking -----------------------------------------------
@pytest.mark.parametrize(
"command",
[
"format C: /q",
"format D: /fs:ntfs",
"&& format",
"| format",
"&format",
";format",
"|format",
],
)
def test_exec_blocks_format_command(command):
"""The Windows ``format`` disk command must be denied."""
tool = ExecTool()
result = tool._guard_command(command, "/tmp")
assert result is not None
assert "deny pattern filter" in result.lower()
@pytest.mark.parametrize(
"command",
[
# URL parameter &format= must NOT be blocked (regression).
'curl -s "wttr.in/xxx?lang=zh&format=%l:+%c+%t+%h+%w&1"',
'curl -s "wttr.in/xxx?format=%l:+%c+%t+%h+%w&1"',
# format as a non-command word in a normal argument.
"echo format",
"echo reformat",
],
)
def test_exec_allows_format_in_url_and_args(command):
"""``format`` inside URL parameters or as a non-command arg must be allowed."""
tool = ExecTool()
result = tool._guard_command(command, "/tmp")
assert result is None