Compare commits

...

2 Commits

Author SHA1 Message Date
Teknium
fa3a9d609d fix: prevent background review agents from creating ghost session files
_spawn_background_review creates a throwaway AIAgent to check if
memories/skills should be saved after each turn. This agent was
created without a session_id, so it auto-generated one and wrote
a full session file (entire conversation snapshot + review prompt)
to sessions/. Every background review created an orphaned file
that cluttered the sessions directory and confused forensics.

Fix: set review_agent.session_log_file = None after creation, and
add an early return in _save_session_log when session_log_file is
falsy. The review agent still runs and saves memories/skills — it
just doesn't write a pointless session file.
2026-03-23 07:12:43 -07:00
Teknium
d33f2a6bcb fix: prevent agents from starting gateway outside systemd management
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
2026-03-23 06:41:21 -07:00
3 changed files with 46 additions and 1 deletions

View File

@@ -1417,6 +1417,11 @@ class AIAgent:
platform=self.platform,
provider=self.provider,
)
# Suppress session file creation — this is a throwaway
# agent whose only job is memory/skill review. Without
# this, every background review writes a ghost session
# file with an auto-generated ID, cluttering sessions/.
review_agent.session_log_file = None
review_agent._memory_store = self._memory_store
review_agent._memory_enabled = self._memory_enabled
review_agent._user_profile_enabled = self._user_profile_enabled
@@ -1892,7 +1897,7 @@ class AIAgent:
Overwritten after each turn so it always reflects the latest state.
"""
messages = messages or self._session_messages
if not messages:
if not messages or not self.session_log_file:
return
try:

View File

@@ -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

View File

@@ -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')"),
]