diff --git a/tests/tools/test_approval.py b/tests/tools/test_approval.py index 0cb4c3571..f6328989f 100644 --- a/tests/tools/test_approval.py +++ b/tests/tools/test_approval.py @@ -456,3 +456,20 @@ class TestViewFullCommand: # After first 'v', is_truncated becomes False, so second 'v' -> deny assert result == "deny" + +class TestForkBombDetection: + """The fork bomb regex must match the classic :(){ :|:& };: pattern.""" + + def test_classic_fork_bomb(self): + dangerous, key, desc = detect_dangerous_command(":(){ :|:& };:") + assert dangerous is True, "classic fork bomb not detected" + assert "fork bomb" in desc.lower() + + def test_fork_bomb_with_spaces(self): + dangerous, key, desc = detect_dangerous_command(":() { : | :& } ; :") + assert dangerous is True, "fork bomb with extra spaces not detected" + + def test_colon_in_safe_command_not_flagged(self): + dangerous, key, desc = detect_dangerous_command("echo hello:world") + assert dangerous is False + diff --git a/tools/approval.py b/tools/approval.py index 7c376f0e9..92da71ca5 100644 --- a/tools/approval.py +++ b/tools/approval.py @@ -38,7 +38,7 @@ DANGEROUS_PATTERNS = [ (r'\bsystemctl\s+(stop|disable|mask)\b', "stop/disable system service"), (r'\bkill\s+-9\s+-1\b', "kill all processes"), (r'\bpkill\s+-9\b', "force kill processes"), - (r':()\s*{\s*:\s*\|\s*:&\s*}\s*;:', "fork bomb"), + (r':\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:', "fork bomb"), (r'\b(bash|sh|zsh)\s+-c\s+', "shell command via -c flag"), (r'\b(python[23]?|perl|ruby|node)\s+-[ec]\s+', "script execution via -e/-c flag"), (r'\b(curl|wget)\b.*\|\s*(ba)?sh\b', "pipe remote content to shell"),