fix: prevent agents from starting gateway outside systemd management (#2617)
An agent session killed the systemd-managed gateway (PID 1605) and restarted it with '&disown', taking it outside systemd's Restart= management. When the orphaned process later received SIGTERM, nothing restarted it. Add dangerous command patterns to detect: - 'gateway run' with & (background), disown, nohup, or setsid - These should use 'systemctl --user restart hermes-gateway' instead Also applied directly to main repo and fixed the systemd service: - Changed Restart=on-failure to Restart=always (clean SIGTERM = exit 0 = not a 'failure', so on-failure never triggered) - RestartSec=10 for reasonable restart delay
This commit is contained in:
@@ -464,3 +464,40 @@ class TestForkBombDetection:
|
||||
dangerous, key, desc = detect_dangerous_command("echo hello:world")
|
||||
assert dangerous is False
|
||||
|
||||
|
||||
class TestGatewayProtection:
|
||||
"""Prevent agents from starting the gateway outside systemd management."""
|
||||
|
||||
def test_gateway_run_with_disown_detected(self):
|
||||
cmd = "kill 1605 && cd ~/.hermes/hermes-agent && source venv/bin/activate && python -m hermes_cli.main gateway run --replace &disown; echo done"
|
||||
dangerous, key, desc = detect_dangerous_command(cmd)
|
||||
assert dangerous is True
|
||||
assert "systemctl" in desc
|
||||
|
||||
def test_gateway_run_with_ampersand_detected(self):
|
||||
cmd = "python -m hermes_cli.main gateway run --replace &"
|
||||
dangerous, key, desc = detect_dangerous_command(cmd)
|
||||
assert dangerous is True
|
||||
|
||||
def test_gateway_run_with_nohup_detected(self):
|
||||
cmd = "nohup python -m hermes_cli.main gateway run --replace"
|
||||
dangerous, key, desc = detect_dangerous_command(cmd)
|
||||
assert dangerous is True
|
||||
|
||||
def test_gateway_run_with_setsid_detected(self):
|
||||
cmd = "hermes_cli.main gateway run --replace &disown"
|
||||
dangerous, key, desc = detect_dangerous_command(cmd)
|
||||
assert dangerous is True
|
||||
|
||||
def test_gateway_run_foreground_not_flagged(self):
|
||||
"""Normal foreground gateway run (as in systemd ExecStart) is fine."""
|
||||
cmd = "python -m hermes_cli.main gateway run --replace"
|
||||
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."""
|
||||
cmd = "systemctl --user restart hermes-gateway"
|
||||
dangerous, key, desc = detect_dangerous_command(cmd)
|
||||
assert dangerous is False
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ 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 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')"),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user