Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion tests/tools/test_approval_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@

import pytest

from tools.approval import detect_dangerous_command
from tools.approval import detect_dangerous_command, detect_hardline_command


def _is_dangerous(cmd: str) -> bool:
res = detect_dangerous_command(cmd)
return bool(res[0]) if isinstance(res, tuple) else bool(res)


def _is_hardline(cmd: str) -> bool:
res = detect_hardline_command(cmd)
return bool(res[0]) if isinstance(res, tuple) else bool(res)


class TestWindowsDestructiveTier:
@pytest.mark.parametrize("cmd", [
# PowerShell destructive delete, bare form (no powershell prefix)
Expand Down Expand Up @@ -108,3 +113,51 @@ def test_windows_credential_paths_flagged(self, cmd):
])
def test_benign_paths_and_posix_escapes_unaffected(self, cmd):
assert not _is_dangerous(cmd), f"should NOT be flagged: {cmd}"


class TestHardlineWindowsDestructiveTier:
"""The Windows destructive tier above (#69472) added Restart-Computer /
Stop-Computer and Format-Volume / format.com to the bypassable
DANGEROUS_PATTERNS only. Both are the direct Windows analogues of two
POSIX HARDLINE_PATTERNS rules — shutdown/reboot/halt/poweroff (system
power state, no recovery path) and mkfs (filesystem format, no recovery
path) — that ARE unconditionally blocked, even under yolo. Before this
fix Restart-Computer/Stop-Computer had NO detection at all (not even a
bypassable prompt), and Format-Volume/format.com could be waved through
with --yolo despite being exactly the kind of no-recovery-path
operation the hardline floor exists to stop.
"""

@pytest.mark.parametrize("cmd", [
"Restart-Computer",
"Restart-Computer -Force",
"restart-computer -force",
"Stop-Computer",
"Stop-Computer -Force",
])
def test_power_state_commands_are_hardline(self, cmd):
assert _is_hardline(cmd), f"should be hardline-blocked: {cmd}"

@pytest.mark.parametrize("cmd", [
"Format-Volume -DriveLetter D",
"format d: /fs:ntfs",
"format D: /y",
])
def test_format_commands_are_hardline(self, cmd):
assert _is_hardline(cmd), f"should be hardline-blocked: {cmd}"

@pytest.mark.parametrize("cmd", [
# Not the destructive cmdlets at all.
"restart the computer manually",
"Get-Service | Restart-Service -Name spooler",
# diskpart is interactive and has non-destructive subcommands
# (list disk); it stays in DANGEROUS_PATTERNS only, matching how
# fdisk/parted are not in the POSIX hardline list either.
"diskpart /s wipe.txt",
# Bare "format" with no drive letter is cmd.exe's own usage/help
# invocation, not a format-in-progress.
"format",
"format /?",
])
def test_benign_or_non_hardline_commands_not_flagged(self, cmd):
assert not _is_hardline(cmd), f"should NOT be hardline-blocked: {cmd}"
11 changes: 11 additions & 0 deletions tools/approval.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,17 @@ def _hardline_rm_path(path_alt: str, tail: str = r'(?:\s|$|[)`;|&])') -> str:
(_CMDPOS + r'init\s+[06]\b', "init 0/6 (shutdown/reboot)"),
(_CMDPOS + r'systemctl\s+(poweroff|reboot|halt|kexec)\b', "systemctl poweroff/reboot"),
(_CMDPOS + r'telinit\s+[06]\b', "telinit 0/6 (shutdown/reboot)"),
# Windows analogues of the two rules above (#69472 follow-up). Neither
# is bare English prose like "reboot"/"shutdown" (which need _CMDPOS to
# avoid matching inside strings/comments), so plain \b word-boundary
# matching is enough here — same style as the Windows tier below in
# DANGEROUS_PATTERNS. These were previously undetected entirely (not
# even a bypassable approval prompt): power-state change with no
# recovery path, and filesystem format with no recovery path, matching
# the "wipe the disk or power the box off" floor this list exists for.
(r'\b(?:restart|stop)-computer\b', "system shutdown/reboot (PowerShell)"),
(r'\bformat-volume\b', "format filesystem (Format-Volume)"),
(r'\bformat(?:\.com)?\s+[a-z]:', "format drive (format.com)"),
]

# Pre-compiled variant used by the hot-path matcher. Building these at module
Expand Down
Loading