Skip to content

fix(mcp): let embedding hosts pin the process home for routed-profile detection - #119355

Open
karangehlod wants to merge 1 commit into
NousResearch:mainfrom
karangehlod:fix/pin-process-hermes-home
Open

karangehlod wants to merge 1 commit into
NousResearch:mainfrom
karangehlod:fix/pin-process-hermes-home

Conversation

@karangehlod

@karangehlod karangehlod commented Sep 22, 2026 •

Copy link
Copy Markdown

What does this PR do?

Fixes all four launch-home decisions that flip when an embedding host mirrors the active turn's profile into `os.environ["HERMES_HOME"]` per turn (confirmed broken on main @ a27b130, #119242):

Decision Broken without fix Fixed by
`serves_routed_profile()` MCP connections fall back to bare cross-profile names `get_process_hermes_home()` returns pinned value
`_is_routed_home()` `strip_launch_profile_env` leaves launch residue in child env same
`_is_process_home()` `GATEWAY_ALLOW_ALL_USERS` grant seeded into served scope same
`env_loader._process_hermes_home()` terminal.* config bridges into shared process env same

Root cause. All four decisions call `get_process_hermes_home()`, which reads `HERMES_HOME` live. When the host mirrors the served home there, all four flip.

Fix. `get_process_hermes_home()` now returns a pinned value when one is set, so every caller is fixed at once without touching their call sites. The pin is set by:

  • `pin_process_hermes_home(launch_home)` — explicit, for embedding hosts (first call wins; `None` clears).
  • `set_multiplex_active(True)` — auto-pins the current `get_process_hermes_home()` value so multiplexed gateways are covered with no extra calls.

Standalone invocations (no multiplex, no explicit pin) keep following `HERMES_HOME` exactly as before.

Related Issue

Fixes #119242.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • `hermes_constants.py`: add `_PINNED_PROCESS_HERMES_HOME` (module-level, `None` by default), `pin_process_hermes_home(path | None)` (first-pin-wins, `None` clears), and move the pin check into `get_process_hermes_home()` itself. `get_routing_process_hermes_home()` kept as a backward-compat alias.
  • `agent/secret_scope.py`: `set_multiplex_active(True)` auto-pins via `pin_process_hermes_home(get_process_hermes_home())`; `serves_routed_profile()` reverted to use `get_process_hermes_home()` (now pin-aware).
  • `tests/agent/test_serves_routed_profile_pin.py` (new, 9 tests): unpinned semantics unchanged; pin survives mirrored env; first-pin-wins; multiplex auto-pin; explicit-pin-before-multiplex; and the three previously-broken decisions (`_is_routed_home`, `_is_process_home`, `env_loader._process_hermes_home`).

How to Test

pytest tests/agent/test_serves_routed_profile_pin.py -q
# 9 passed (all fail on main without this change)

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs — not a duplicate
  • My PR contains only changes related to this fix
  • I've added tests for my changes

Documentation & Housekeeping

  • Docstrings updated on `pin_process_hermes_home`, `get_process_hermes_home`, `set_multiplex_active`
  • Cross-platform: pure path comparison through existing `_expand_hermes_home`; no OS-specific code
  • `cli-config.yaml.example` — N/A (no config key added)

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint tool/mcp MCP client and OAuth area/profiles Multi-profile isolation, HERMES_HOME scoping sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data labels Sep 22, 2026
… detection

Fixes all four launch-home decisions that flip when a host mirrors
the served profile into os.environ["HERMES_HOME"] per turn (NousResearch#119242):

  * serves_routed_profile() - MCP registry scope / connection key
  * _is_routed_home() - strip_launch_profile_env residue in child env
  * _is_process_home() - GATEWAY_ALLOW_ALL_USERS seeding into served scope
  * env_loader._process_hermes_home() - terminal.* config cross-profile leak

Changes:
- hermes_constants.pin_process_hermes_home(path): records the host own home
  (first call wins; None clears). get_process_hermes_home() returns the pinned
  value when set, so all four callers are fixed without touching their call sites.
- agent.secret_scope.set_multiplex_active(True) now calls
  pin_process_hermes_home() so multiplexed gateways are covered automatically.
  An embedding host that calls pin_process_hermes_home() before activating
  multiplex keeps its own pin (first-pin-wins).
- get_routing_process_hermes_home() kept as an alias for backward compat.
- 9 tests covering: unpinned semantics unchanged, pin survives mirrored env,
  first-pin-wins, multiplex auto-pin, explicit-pin-before-multiplex,
  _is_routed_home, _is_process_home, env_loader._process_hermes_home.

Fixes NousResearch#119242.

This branch has not been deployed

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

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state tool/mcp MCP client and OAuth type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: a host that mirrors the served profile into HERMES_HOME defeats serves_routed_profile(): MCP connections fall back to bare cross-profile names

2 participants