diff --git a/tests/tools/test_approval.py b/tests/tools/test_approval.py index bbd11cd45c..661b86bf3f 100644 --- a/tests/tools/test_approval.py +++ b/tests/tools/test_approval.py @@ -550,11 +550,12 @@ class TestGatewayProtection: dangerous, key, desc = detect_dangerous_command(cmd) assert dangerous is False - def test_systemctl_restart_not_flagged(self): - """Using systemctl to manage the gateway is the correct approach.""" + def test_systemctl_restart_flagged(self): + """systemctl restart kills running agents and should require approval.""" cmd = "systemctl --user restart hermes-gateway" dangerous, key, desc = detect_dangerous_command(cmd) - assert dangerous is False + assert dangerous is True + assert "stop/restart" in desc def test_pkill_hermes_detected(self): """pkill targeting hermes/gateway processes must be caught.""" diff --git a/tools/approval.py b/tools/approval.py index 3e9ccdf75e..d2d50a19ae 100644 --- a/tools/approval.py +++ b/tools/approval.py @@ -87,7 +87,7 @@ DANGEROUS_PATTERNS = [ (r'\bDELETE\s+FROM\b(?!.*\bWHERE\b)', "SQL DELETE without WHERE"), (r'\bTRUNCATE\s+(TABLE)?\s*\w', "SQL TRUNCATE"), (r'>\s*/etc/', "overwrite system config"), - (r'\bsystemctl\s+(stop|disable|mask)\b', "stop/disable system service"), + (r'\bsystemctl\s+(-[^\s]+\s+)*(stop|restart|disable|mask)\b', "stop/restart 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*\}\s*;\s*:', "fork bomb"), @@ -101,6 +101,11 @@ DANGEROUS_PATTERNS = [ (r'\bxargs\s+.*\brm\b', "xargs with rm"), (r'\bfind\b.*-exec\s+(/\S*/)?rm\b', "find -exec rm"), (r'\bfind\b.*-delete\b', "find -delete"), + # Gateway lifecycle protection: prevent the agent from killing its own + # gateway process. These commands trigger a gateway restart/stop that + # terminates all running agents mid-work. + (r'\bhermes\s+gateway\s+(stop|restart)\b', "stop/restart hermes gateway (kills running agents)"), + (r'\bhermes\s+update\b', "hermes update (restarts gateway, kills running agents)"), # Gateway protection: never start gateway outside systemd management (r'gateway\s+run\b.*(&\s*$|&\s*;|\bdisown\b|\bsetsid\b)', "start gateway outside systemd (use 'systemctl --user restart hermes-gateway')"), (r'\bnohup\b.*gateway\s+run\b', "start gateway outside systemd (use 'systemctl --user restart hermes-gateway')"),