hermes-agent/hermes_cli
Teknium f456f302df
fix(gateway): refuse to write service definitions with a temp-dir HERMES_HOME (#44267)
* fix(gateway): refuse to write service definitions with a temp-dir HERMES_HOME

A test/E2E harness that exports HERMES_HOME=/tmp/... and touches any
gateway service write path (install, start self-heal, restart's
refresh_systemd_unit_if_needed) bakes the throwaway home into the
production systemd unit / launchd plist. The gateway then restarts
'healthy' but pointed at an empty temp home — no platforms enabled,
deaf to every message (live incident 2026-06-11: /tmp/hermes-e2e-41264
poisoned the unit during a PR-review E2E probe; the post-update restart
produced a 7-hour zombie gateway).

The existing safety belt only sniffed pytest-shaped markers
(/pytest-of-, /hermes_test). Add a structural guard:
_temp_home_in_service_definition() extracts HERMES_HOME from the
generated systemd unit or launchd plist and refuses the write (with
actionable guidance) when it resolves under tempfile.gettempdir(),
/tmp, /var/tmp, or the macOS /private variants. Wired into all five
write sites: systemd refresh + install, launchd refresh + install +
start self-heal.

* test: patch unit generator in install tests tripped by temp-home guard

CI runs hermetic with HERMES_HOME under a tmp dir, so the real
generate_systemd_unit() output now (correctly) trips the new temp-home
write guard in three install tests. Patch the generator with synthetic
non-temp content — same pattern the existing pytest-marker guard tests
use.
2026-06-11 06:10:08 -07:00
..
dashboard_auth fix(dashboard-auth): warn when public_url override is silently rejected (#43214) 2026-06-10 12:14:57 +10:00
proxy
…
subcommands feat(dashboard): unify multi-profile management — one machine dashboard, global profile switcher (#44007) 2026-06-11 03:29:33 -07:00
__init__.py fix(cli): repair non-UTF-8 stdout/stderr on all platforms, not just Windows (#43439) 2026-06-10 02:21:00 -07:00
_parser.py
…
_subprocess_compat.py
…
active_sessions.py feat(sessions): add optional max session cap 2026-06-08 15:12:12 -07:00
auth.py fix(model): require confirmation for expensive model selections 2026-06-10 00:24:06 -07:00
auth_commands.py fix(auth): add Codex OAuth accounts as distinct pool entries 2026-06-08 11:57:03 -07:00
azure_detect.py
…
backup.py fix(backup): stage SQLite snapshots beside output zip in pre-update path too 2026-06-11 12:45:40 +05:30
banner.py fix(update): avoid SSH auth for passive official checks 2026-06-11 12:45:07 +05:30
browser_connect.py
…
build_info.py
…
bundles.py
…
callbacks.py
…
checkpoints.py
…
claw.py
…
cli_agent_setup_mixin.py fix(cli): gate tool-rendering paths with tool_progress_mode, not quiet_mode 2026-06-08 11:29:53 -07:00
cli_commands_mixin.py refactor(memory,skills): replace tri-state write_mode with boolean write_approval (default off) (#43354) 2026-06-09 23:21:14 -07:00
cli_output.py
…
clipboard.py
…
codex_models.py
…
codex_runtime_plugin_migration.py
…
codex_runtime_switch.py
…
colors.py
…
commands.py desktop: registry-driven slash commands + first-class /resume & /handoff (#42351) 2026-06-11 01:49:24 +00:00
completion.py
…
config.py feat(agent): coding-context posture across CLI/TUI/desktop/ACP (#43316) 2026-06-10 23:06:44 -05:00
container_boot.py
…
copilot_auth.py
…
cron.py revert(cron): remove per-job profile support (PR #28124) (#43956) 2026-06-10 20:46:17 -07:00
curator.py
…
curses_ui.py
…
dashboard_register.py fix(cli): persist custom --portal-url to .env on dashboard register (#42435) 2026-06-09 13:56:33 +10:00
debug.py
…
default_soul.py
…
dep_ensure.py
…
dingtalk_auth.py
…
doctor.py fix(state.db): recover from malformed sqlite_master so hidden sessions reappear (#43149) 2026-06-09 18:49:08 -05:00
dump.py fix(auth): auto-detect OpenRouter credential from the pool, not just env (#42263) 2026-06-08 10:01:47 -07:00
env_loader.py
…
fallback_cmd.py
…
fallback_config.py
…
gateway.py fix(gateway): refuse to write service definitions with a temp-dir HERMES_HOME (#44267) 2026-06-11 06:10:08 -07:00
gateway_windows.py
…
goals.py
…
gui_uninstall.py
…
hooks.py
…
inventory.py
…
kanban.py
…
kanban_db.py
…
kanban_decompose.py
…
kanban_diagnostics.py
…
kanban_specify.py
…
kanban_swarm.py
…
logs.py
…
main.py feat(dashboard): unify multi-profile management — one machine dashboard, global profile switcher (#44007) 2026-06-11 03:29:33 -07:00
managed_uv.py
…
mcp_catalog.py
…
mcp_config.py
…
mcp_picker.py
…
mcp_startup.py
…
memory_setup.py
…
middleware.py
…
migrate.py
…
model_catalog.py feat(models): seed model-catalog disk cache from checkout on update (#42614) 2026-06-08 22:31:06 -07:00
model_cost_guard.py fix(model): require confirmation for expensive model selections 2026-06-10 00:24:06 -07:00
model_normalize.py
…
model_setup_flows.py fix(model): require confirmation for expensive model selections 2026-06-10 00:24:06 -07:00
model_switch.py
…
models.py fix(models): keep curated Anthropic aliases in /model picker (#43103) 2026-06-09 14:45:19 -07:00
nous_account.py
…
nous_subscription.py
…
oneshot.py
…
pairing.py
…
partial_compress.py
…
platforms.py
…
plugins.py
…
plugins_cmd.py feat(plugins): install from a subdirectory within a repo (#42963) 2026-06-09 13:42:51 -04:00
portal_cli.py
…
profile_describer.py
…
profile_distribution.py
…
profiles.py fix(desktop): release profile backends before delete (#42613) 2026-06-09 10:52:02 -05:00
prompt_size.py
…
providers.py fix(doctor): allow vendor slugs for named custom providers 2026-06-08 15:53:09 -07:00
psutil_android.py
…
pt_input_extras.py
…
pty_bridge.py fix(pty-bridge): mark os.killpg/getpgid windows-footgun-ok (POSIX-only module) 2026-06-08 07:03:12 -07:00
relaunch.py
…
runtime_provider.py fix(cron): resolve per-job provider "custom" to providers.custom instead of codex 2026-06-10 14:39:03 -07:00
secret_prompt.py
…
secrets_cli.py
…
security_advisories.py
…
security_audit.py
…
send_cmd.py
…
service_manager.py fix(gateway): auto-start after container restart via planned-stop marker (#42675) (#43236) 2026-06-10 14:01:34 +10:00
session_recap.py
…
setup.py
…
skills_config.py
…
skills_hub.py feat(skills): show live per-source progress while browsing (#43398) 2026-06-10 01:02:40 -07:00
skin_engine.py
…
slack_cli.py
…
status.py
…
stdio.py
…
telegram_managed_bot.py
…
timeouts.py
…
tips.py
…
tools_config.py feat(agent): coding-context posture across CLI/TUI/desktop/ACP (#43316) 2026-06-10 23:06:44 -05:00
uninstall.py
…
voice.py
…
web_server.py fix(dashboard): normalize model assignments + confirm-modal for backup import (#44237) 2026-06-11 05:07:58 -07:00
webhook.py
…
win_pty_bridge.py feat(windows): enable dashboard /chat tab via ConPTY (win_pty_bridge) + tests (#42251) 2026-06-08 11:32:43 -07:00
write_approval_commands.py refactor(memory,skills): replace tri-state write_mode with boolean write_approval (default off) (#43354) 2026-06-09 23:21:14 -07:00
xai_retirement.py
…