Skip to content

fix(gateway): resolve external secret sources for cold multiplex profiles (#74317) - #75047

Closed
webtecnica wants to merge 1 commit into
NousResearch:mainfrom
webtecnica:fix/74317-multiplex-cold-secrets
Closed

fix(gateway): resolve external secret sources for cold multiplex profiles (#74317)#75047
webtecnica wants to merge 1 commit into
NousResearch:mainfrom
webtecnica:fix/74317-multiplex-cold-secrets

Conversation

@webtecnica

Copy link
Copy Markdown
Contributor

Fixes #74317 — cold multiplex profiles now resolve external secret sources (1Password, Bitwarden) before the first routed turn. Added _apply_external_secret_sources(profile_home) at the start of _profile_runtime_scope().

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery area/auth Authentication, OAuth, credential pools area/config Config system, migrations, profiles area/profiles Multi-profile isolation, HERMES_HOME scoping sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Jul 30, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for locating the missing cold-profile handoff in _profile_runtime_scope(); current main does build the profile scope before any source hydration (gateway/run.py:1803-1804). The proposed call needs a profile-local implementation rather than the startup resolver.

Problems

  • _apply_external_secret_sources() is process-global: it calls apply_all() with the default environment (hermes_cli/env_loader.py:421-427) and snapshots values by reading os.environ (hermes_cli/env_loader.py:453-458). Existing coverage demonstrates that applying home B overwrites the shared environment value (tests/test_env_loader_secret_sources.py:305-319). Calling it for a routed profile would reintroduce the cross-profile exposure the multiplex scope prevents.
  • It also runs before the profile .env is parsed into the scope. Bitwarden source authentication reads its bootstrap token from os.environ (agent/secret_sources/bitwarden.py:910-918), and .op.env is only loaded by the normal dotenv startup path (hermes_cli/env_loader.py:324-342), which this call bypasses.

Suggested changes

  • Hydrate through an isolated per-profile mapping, including supported bootstrap files, and persist only the resulting per-home snapshot.
  • Add a first-routed-secondary-profile regression that proves scoped resolution and no os.environ leakage.

This is an automated hermes-sweeper review.

@teknium1

teknium1 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Thanks @webtecnica — reviewed against current origin/main (dbb6acd) in the multiplexed-gateway backlog sweep.

Closing as redundant: the cold-profile handoff you identified was fixed in 6ab390a (part of #76573, merged 2026-08-02) with a profile-private implementation rather than the process-global _apply_external_secret_sources() this PR called. On main _profile_runtime_scope() runs hydrate_profile_secret_sources(Path(profile_home)) before building the secret scope (gateway/run.py:2574-2578), and that helper resolves the profile's configured sources against a private mapping seeded from its own .env without touching os.environ (hermes_cli/env_loader.py:169-185). #74317 is closed on the same fix.

Credit: you located the missing handoff in _profile_runtime_scope() three days before it landed; the review above explains why the shape had to change (the startup resolver snapshots from os.environ, which would have re-leaked across profiles). If a cold secondary profile still can't see a Bitwarden/1Password value, a fresh report needs its secrets.yaml, whether the bootstrap token is in the profile .env or process env, and the first-turn get_secret miss.

@teknium1 teknium1 closed this Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools area/config Config system, migrations, profiles area/profiles Multi-profile isolation, HERMES_HOME scoping comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(secrets): cold multiplex profiles do not resolve configured external sources into their secret scope

3 participants