Skip to content

fix(terminal): block gateway lifecycle commands from inside the gateway process#37475

Open
AhmetArif0 wants to merge 1 commit into
NousResearch:mainfrom
AhmetArif0:fix/terminal-gateway-lifecycle-guard
Open

fix(terminal): block gateway lifecycle commands from inside the gateway process#37475
AhmetArif0 wants to merge 1 commit into
NousResearch:mainfrom
AhmetArif0:fix/terminal-gateway-lifecycle-guard

Conversation

@AhmetArif0

Copy link
Copy Markdown
Contributor

Summary

Closes #37453.

systemctl --user restart hermes-gateway run from the terminal tool is a child process of the gateway. When systemd delivers SIGTERM, the gateway kills this subprocess before it can complete — the service may never restart (deadlock).

The hermes gateway restart/stop guard (hermes_cli/gateway.py) and the cron-path guard (hermes_cli/cron.py) already block equivalent commands in their respective paths, but the terminal tool had no such defense.

Changes

tools/terminal_tool.py — hard-block before execution: when _HERMES_GATEWAY=1 and the command matches _contains_gateway_lifecycle_command, return an error immediately. force=True cannot bypass it — unlike the normal dangerous-command approval flow, a user-approved restart would still fail because SIGTERM propagates to child processes.

hermes_cli/cron.py — extend _GATEWAY_LIFECYCLE_PATTERNS to match systemctl with flags (e.g. systemctl --user restart). The previous regex required the action word immediately after systemctl with no flags in between, so systemctl --user restart hermes-gateway (the exact command from the issue) was not caught.

Test plan

  • test_blocks_lifecycle_commands_inside_gateway — 6 variants: systemctl restart/stop, systemctl --user restart, hermes gateway restart, launchctl kickstart, pkill
  • test_force_true_cannot_bypass_blockforce=True does not help
  • test_safe_systemctl_commands_pass_throughsystemctl status nginx is not blocked inside gateway
  • test_guard_inactive_outside_gateway — guard only fires when _HERMES_GATEWAY=1
  • All 42 existing test_gateway_restart_loop.py tests still pass

…ay process

systemctl --user restart hermes-gateway run via the terminal tool is a
child of the gateway itself. When systemd delivers SIGTERM the gateway
kills this subprocess before it can complete, so the service may never
restart — reproducing issue NousResearch#37453.

The hermes gateway restart/stop guard (hermes_cli/gateway.py) and the
cron-path guard (hermes_cli/cron.py) already block equivalent commands
in their respective paths but the terminal tool had no such defense.

Add a hard-block before command execution in terminal_tool: when
_HERMES_GATEWAY=1 and the command matches _contains_gateway_lifecycle_command,
return an error immediately. force=True cannot bypass it — unlike the
normal dangerous-command approval flow, here even a user-approved restart
would fail because the SIGTERM propagates to child processes.

Also extend _GATEWAY_LIFECYCLE_PATTERNS to match systemctl with flags
(e.g. systemctl --user restart) — the previous regex required the
action word immediately after systemctl with no flags in between.

Adds 9 regression tests: 6 blocked variants (parametrized), force bypass
attempt, safe systemctl passthrough, and guard-inactive-outside-gateway.
@alt-glitch alt-glitch added type/bug Something isn't working tool/terminal Terminal execution and process management comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery P1 High — major feature broken, no workaround labels Jun 2, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

Important safety fix: adds a hard block in terminal_tool against gateway lifecycle commands (systemctl restart hermes-gateway, hermes gateway restart, launchctl kickstart ..., pkill ...) when executed from inside the gateway process itself. Without this guard, restarting the gateway from within kills the child process mid-execution before the restart can complete.

✅ Looks Good

  • Comprehensive regex update in cron.py to also match systemctl --user ... variants
  • 4 carefully designed tests: block lifecycle commands, force bypass test, safe commands pass through, guard inactive outside gateway
  • Clean inline comment explaining the issue
  • No security concerns — blocking gateway restarts from within the gateway is the correct behavior

Reviewed by Hermes Agent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery P1 High — major feature broken, no workaround tool/terminal Terminal execution and process management type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gateway: systemctl restart from inside terminal tool deadlocks — kills itself mid-execution

3 participants