Skip to content

Fix(gateway/cron): resolve BWS multiplexing credential isolation, OAuth path hijack, and cron scheduler thread safety - #57563

Closed
austinlaw076 wants to merge 11 commits into
NousResearch:mainfrom
austinlaw076:fix/multiplex-env-pollution
Closed

Fix(gateway/cron): resolve BWS multiplexing credential isolation, OAuth path hijack, and cron scheduler thread safety#57563
austinlaw076 wants to merge 11 commits into
NousResearch:mainfrom
austinlaw076:fix/multiplex-env-pollution

Conversation

@austinlaw076

@austinlaw076 austinlaw076 commented Jul 3, 2026

Copy link
Copy Markdown

This PR fixes critical multiplex_profiles logic flaws, BWS/OAuth credential leakage, cron scheduler thread safety, and profile-aware adapter routing.

Key fixes:

  1. Multiplex env override interceptor (fixes gateway.multiplex_profiles: secondary profiles connect with the active profile's token (platform credentials read from os.environ, bypassing the per-profile secret scope) #52446)
  2. BWS credential scoping in cron threads
  3. Scheduler locking and thread safety
  4. Heartbeat per-profile success state
  5. Anthropic OAuth dynamic home resolution
  6. Profile-aware adapter routing: _resolve_adapter_for_source() replaces all 47 self.adapters.get(source.platform) call sites. Previously secondary profile responses were delivered via the default profile bot. Now streaming/media/typing/progress/errors route through the correct profile-specific adapter.
  7. Regression tests

E2E: Mark bot (@mark076_bot) now replies in its own Telegram chat with grok-4.3 via xai.

Fixes #52446, #52307, #52796. Relates to #56302.

@alt-glitch alt-glitch added type/security Security vulnerability or hardening comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/gateway Gateway runner, session dispatch, delivery area/auth Authentication, OAuth, credential pools P2 Medium — degraded but workaround exists 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 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #56302 (OPEN — fixes the SAME import-time-freeze of the Anthropic OAuth file path in agent/anthropic_adapter.py/hermes_cli/web_server.py that causes the cross-profile credential write; it additionally re-resolves auxiliary_client._AUTH_JSON_PATH and gateway/mirror._SESSIONS_INDEX, which this PR does not touch). This PR is not a duplicate — it adds gateway/config.py secondary-profile port-disable + env-override gating (#52307/#52446/#52796) that #56302 lacks. A maintainer should reconcile the overlapping OAuth-resolver half between the two.

@egilewski

Copy link
Copy Markdown
Contributor

suggesting changes

Security evidence:

  • trust boundary: multiplexed gateway startup must construct each secondary profile's platform adapters from that profile's own HERMES_HOME and secret scope; process-global environment values from the active/default profile must not leak into secondary adapters, but secondary profile credentials must still be loaded.
  • source/sink/invariant: the source is _apply_env_overrides() reading platform tokens/settings while set_hermes_home_override() and set_secret_scope() point at a secondary profile; the sink is GatewayConfig.platforms[...] used to start adapters; the invariant is that a secondary profile with its own .env gets its own token, not the process-global token and not an empty platform config.
  • current-main reproduction: importing gateway.config from current GitHub main 5e2b051, a run-root probe with HERMES_HOME=<root>/profiles/coder, scoped .env containing DISCORD_BOT_TOKEN=secondary-token, and process env DISCORD_BOT_TOKEN=primary-token produced discord_enabled=True and discord_token=primary-token, reproducing the cross-profile leak from gateway.multiplex_profiles: secondary profiles connect with the active profile's token (platform credentials read from os.environ, bypassing the per-profile secret scope) #52446.
  • PR-head validation: importing gateway.config from PR head 8215bf6, the same probe printed gateway_config_file from the PR worktree and produced discord_enabled=None and discord_token=None; the PR avoids the leak by returning before secondary env overrides, but it still does not load the secondary profile's scoped token, so the multiplexed adapter would not get its own credentials.
  • remaining blocker: the new early if is_secondary: return in _apply_env_overrides() bypasses the platform token/settings override path for every secondary profile instead of migrating those reads to the active profile secret scope. That leaves gateway.multiplex_profiles: secondary profiles connect with the active profile's token (platform credentials read from os.environ, bypassing the per-profile secret scope) #52446's core requirement incomplete for Discord and the same pattern of platform settings read through this function.
  • reviewer validation: git merge-tree --write-tree 5e2b051 8215bf6 succeeded, and the submitted focused tests passed as 80 passed for tests/gateway/test_config.py tests/hermes_cli/test_web_server_oauth_write.py, but those tests do not cover scoped secondary .env credential resolution. git diff --check 5e2b051...8215bf6 also fails on trailing whitespace in gateway/config.py:1268.

Please change the secondary-profile path so _apply_env_overrides() resolves platform tokens and settings from the active profile secret scope, or an equivalent profile-scoped source, rather than skipping overrides entirely or reading the process-global environment. Add a regression with a secondary profile .env token that differs from os.environ["DISCORD_BOT_TOKEN"], and fix the trailing whitespace before the next pass.

@austinlaw076

Copy link
Copy Markdown
Author

suggesting changes

Security evidence:

  • trust boundary: multiplexed gateway startup must construct each secondary profile's platform adapters from that profile's own HERMES_HOME and secret scope; process-global environment values from the active/default profile must not leak into secondary adapters, but secondary profile credentials must still be loaded.
  • source/sink/invariant: the source is _apply_env_overrides() reading platform tokens/settings while set_hermes_home_override() and set_secret_scope() point at a secondary profile; the sink is GatewayConfig.platforms[...] used to start adapters; the invariant is that a secondary profile with its own .env gets its own token, not the process-global token and not an empty platform config.
  • current-main reproduction: importing gateway.config from current GitHub main 5e2b051, a run-root probe with HERMES_HOME=<root>/profiles/coder, scoped .env containing DISCORD_BOT_TOKEN=secondary-token, and process env DISCORD_BOT_TOKEN=primary-token produced discord_enabled=True and discord_token=primary-token, reproducing the cross-profile leak from gateway.multiplex_profiles: secondary profiles connect with the active profile's token (platform credentials read from os.environ, bypassing the per-profile secret scope) #52446.
  • PR-head validation: importing gateway.config from PR head 8215bf6, the same probe printed gateway_config_file from the PR worktree and produced discord_enabled=None and discord_token=None; the PR avoids the leak by returning before secondary env overrides, but it still does not load the secondary profile's scoped token, so the multiplexed adapter would not get its own credentials.
  • remaining blocker: the new early if is_secondary: return in _apply_env_overrides() bypasses the platform token/settings override path for every secondary profile instead of migrating those reads to the active profile secret scope. That leaves gateway.multiplex_profiles: secondary profiles connect with the active profile's token (platform credentials read from os.environ, bypassing the per-profile secret scope) #52446's core requirement incomplete for Discord and the same pattern of platform settings read through this function.
  • reviewer validation: git merge-tree --write-tree 5e2b051 8215bf6 succeeded, and the submitted focused tests passed as 80 passed for tests/gateway/test_config.py tests/hermes_cli/test_web_server_oauth_write.py, but those tests do not cover scoped secondary .env credential resolution. git diff --check 5e2b051...8215bf6 also fails on trailing whitespace in gateway/config.py:1268.

Please change the secondary-profile path so _apply_env_overrides() resolves platform tokens and settings from the active profile secret scope, or an equivalent profile-scoped source, rather than skipping overrides entirely or reading the process-global environment. Add a regression with a secondary profile .env token that differs from os.environ["DISCORD_BOT_TOKEN"], and fix the trailing whitespace before the next pass.

Hey @egilewski, thanks for the review! I’ve just updated the PR branch with the following changes:

  1. Fixed Secondary Profile Path Handling: Updated the logic in applyenvoverrides. Now it uses the getsecret interceptor to resolve platform tokens and settings from the active profile’s secret scope, instead of skipping overrides or falling back to global os.environ.

  2. Added Regression Test: Added testsecondaryprofileenvoverridesresolvesfromscope in tests/gateway/testmultiplexcredentialisolation.py to make sure secondary profile dotenv tokens correctly override global env vars.

  3. Code Cleanup: Cleared out all the trailing whitespaces in the affected files.

Mind taking another look? Thanks!

@alt-glitch alt-glitch added the comp/cli CLI entry point, hermes_cli/, setup wizard label Jul 4, 2026
@austinlaw076 austinlaw076 changed the title Fix OAuth path hijack and improve gateway dynamic resolution Fix(gateway/cron): resolve BWS multiplexing credential isolation, OAuth path hijack, and cron scheduler thread safety Jul 4, 2026
@egilewski

Copy link
Copy Markdown
Contributor

suggesting changes

Security evidence:

  • trust boundary: this PR is security-labeled because it changes OAuth/profile credential resolution and multiplexed gateway startup, so the review needs to be able to reason about one coherent auth/profile boundary.
  • source/sink/invariant: the intended source/sink path is profile-scoped secret and OAuth path resolution flowing into gateway and dashboard credential consumers; unrelated runtime/plugin changes should not be bundled into the same security fix because they change different behavior and make focused validation misleading.
  • current-main reproduction: not run after the convention screen, because the PR shape itself makes a focused security comparison premature.
  • PR-head validation: bounded PR metadata shows the head changes 24 files, including the OAuth/gateway/profile files, cron scheduler/job code, Telegram adapter code, local environment setup, and a new plugins/continuity subtree of roughly 2,800 added lines.
  • positive/negative cases: not run after the convention screen; the first blocker is review scope, not a source-level regression found in a behavior probe.
  • residual bypass search: not run because the PR mixes the stated OAuth/gateway fix with a new continuity plugin and unrelated cron/Telegram/environment changes, so any residual-bypass result would be hard to attribute to the intended security fix.
  • reviewer validation: CONTRIBUTING.md says to keep PRs to one logical change and not mix a bug fix with a refactor or new feature; it also says PRs adding new directories under plugins/ should be published as standalone plugin repos. This PR's description is about OAuth path hijack, gateway dynamic resolution, and multiplex profile handling, but the changed-file list includes plugins/continuity/**, cron/**, plugins/platforms/telegram/adapter.py, and tools/environments/local.py.

Please split the continuity plugin and the unrelated cron/Telegram/environment changes out of this PR, then keep this branch focused on the OAuth/gateway/profile credential fix and its direct tests. I stopped at this first serious convention issue, so there may be additional source-level review comments once the security fix is isolated.

Signed: GPT-5.5-xhigh in Codex

@alt-glitch alt-glitch added comp/cron Cron scheduler and job management comp/plugins Plugin system and bundled plugins platform/telegram Telegram bot adapter backend/local Local shell execution labels Jul 4, 2026
…d cron, telegram, and continuity plugin modifications
@austinlaw076

Copy link
Copy Markdown
Author

│ Hi @egilewski, thanks for pointing out the scope
│ convention!

│ I have clean-split the PR:

│ 1. Reverted all unrelated changes in cron/ , tools/ ,
│ and plugins/platforms/telegram/ .
│ 2. Removed the newly added plugins/continuity
│ directory entirely from this branch.
│ 3. Kept this PR strictly focused on the Anthropic OAuth
│ path hijack fix, dynamic home path resolution, multiplex
│ profile environment overrides, and their corresponding
│ test suite (
│ tests/gateway/test_multiplex_credential_isolation.py ).

│ The unrelated fixes and the new plugin will be submitted
│ in separate PRs later. Please take another look at the
│ isolated credential fixes. Thanks!

@alt-glitch alt-glitch added comp/dashboard Web dashboard / control panel UI (dashboard/, landing) and removed comp/cli CLI entry point, hermes_cli/, setup wizard comp/cron Cron scheduler and job management comp/plugins Plugin system and bundled plugins platform/telegram Telegram bot adapter backend/local Local shell execution labels Jul 4, 2026
@alt-glitch alt-glitch removed the P2 Medium — degraded but workaround exists label Jul 4, 2026
@alt-glitch alt-glitch added comp/dashboard Web dashboard / control panel UI (dashboard/, landing) provider/anthropic Anthropic native Messages API and removed sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/cli CLI entry point, hermes_cli/, setup wizard labels Jul 4, 2026
…ing secret-scope bypass paths

- gateway/config.py: remove getattr(config, 'multiplex_profiles') from
  port-binding force-disable — secondary profiles don't carry the multiplex
  flag (it lives on the primary gateway config), so the check never triggered.
  Now only checks is_secondary_override.
- gateway/config.py: remove trailing whitespace on blank lines.
- hermes_cli/config.py: get_env_value() now checks get_secret() from the
  active profile's _SECRET_SCOPE before falling back to os.environ, matching
  get_env_value_prefer_dotenv's pattern.
- plugins/platforms/telegram/adapter.py: _standalone_send() resolves
  TELEGRAM_BOT_TOKEN via get_env_value_prefer_dotenv() instead of raw
  os.getenv, preventing cross-profile token leakage in cron delivery.
@alt-glitch alt-glitch added comp/cli CLI entry point, hermes_cli/, setup wizard platform/telegram Telegram bot adapter area/config Config system, migrations, profiles and removed sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 4, 2026
In multiplex mode, self.adapters only holds the default profile's
platform adapters. Secondary profiles (e.g. shadow-reviewer) have their
own adapters in self._profile_adapters[profile][platform]. All 47 call
sites that used self.adapters.get(source.platform) for outbound delivery
(streaming, media, footer, typing indicators, progress bubbles, error
messages, queue management) were sending through the wrong bot — the
default profile's adapter instead of the source profile's adapter.

This adds _resolve_adapter_for_source() which checks source.profile
first and falls back to the default map, and replaces all 47 call sites.

Symptom: secondary profile (Mark bot) generated correct LLM responses
(grok-4.3 via xai) but the streaming consumer delivered them via the
default profile's Telegram bot (Sylvie), so the user never saw Mark's
replies in the Mark bot chat. The gateway log showed 'Suppressing normal
final send' because streaming marked content_delivered=True, but the
content was delivered to the wrong chat.
@alt-glitch alt-glitch removed the comp/dashboard Web dashboard / control panel UI (dashboard/, landing) label Jul 4, 2026
Austin added 3 commits July 4, 2026 17:44
…for_source

Reviewer audit found LOW-severity docstring typo where the helper's
docstring referenced itself instead of the old self.adapters.get() pattern.
@alt-glitch alt-glitch removed the platform/telegram Telegram bot adapter label Jul 4, 2026
@egilewski

Copy link
Copy Markdown
Contributor

suggesting changes

The multiplex credential-isolation change appears to call the secret-scope path before determining whether the active gateway config load is actually a secondary profile read. On a run-owned local merge of this PR head onto current GitHub main, enabling multiplex mode with no installed secret scope made the ordinary primary/default GatewayConfig() env override path raise UnscopedSecretError for TELEGRAM_BOT_TOKEN; the same probe on current main kept the primary/no-profile load on the legacy environment path and completed successfully. Focused credential-isolation and OAuth tests passed in the reviewed merge tree, the local replay against current main was coherent, and the sensitive-path guard remained present in the replayed tree, but the new tests do not cover this primary/default startup case.

Please make _apply_env_overrides() decide whether the active config load is secondary before calling get_secret() for profile-only env names, or otherwise keep primary/no-profile config loads on the legacy os.environ path while multiplex mode is active. Add a regression for set_multiplex_active(True) with no installed secret scope on the primary/default config path, and fix the trailing whitespace / EOF whitespace reported by git diff --check.

Signed: GPT-5.5-xhigh in Codex

@alt-glitch alt-glitch added the comp/plugins Plugin system and bundled plugins label Jul 4, 2026
teknium1 pushed a commit that referenced this pull request Jul 6, 2026
…ing platform gaps

Two focused pieces salvaged from PR #57563:

1. _HERMES_OAUTH_FILE was computed at module import time — frozen before
   HERMES_HOME/profile overrides, so multiplexed profile turns read and
   wrote the DEFAULT profile's .anthropic_oauth.json (OAuth path hijack).
   Replaced with a lazy _get_hermes_oauth_file(); all web_server.py call
   sites updated.

2. _PORT_BINDING_PLATFORM_VALUES was missing whatsapp_cloud and line —
   both bind aiohttp TCP listeners, so a secondary multiplex profile
   enabling them would collide with the primary's listener instead of
   failing fast at startup.

Original work by @austinlaw076. The rest of #57563 was redundant on
main (adapter routing sweep superseded by #56854's salvage; cron secret
scope landed in fdab380; nested-config fallback in from_dict).
benbarclay added a commit that referenced this pull request Jul 7, 2026
…latform set (#57563 salvage) (#59339)

* fix(auth): resolve Anthropic OAuth file per-profile + close port-binding platform gaps

Two focused pieces salvaged from PR #57563:

1. _HERMES_OAUTH_FILE was computed at module import time — frozen before
   HERMES_HOME/profile overrides, so multiplexed profile turns read and
   wrote the DEFAULT profile's .anthropic_oauth.json (OAuth path hijack).
   Replaced with a lazy _get_hermes_oauth_file(); all web_server.py call
   sites updated.

2. _PORT_BINDING_PLATFORM_VALUES was missing whatsapp_cloud and line —
   both bind aiohttp TCP listeners, so a secondary multiplex profile
   enabling them would collide with the primary's listener instead of
   failing fast at startup.

Original work by @austinlaw076. The rest of #57563 was redundant on
main (adapter routing sweep superseded by #56854's salvage; cron secret
scope landed in fdab380; nested-config fallback in from_dict).

* chore(release): map austinlaw076 author email for PR #57563 salvage

* test(hermes_cli): patch _get_hermes_oauth_file instead of removed _HERMES_OAUTH_FILE constant

---------

Co-authored-by: Austin <austin@openvm067.space>
Co-authored-by: Ben <ben@nousresearch.com>
@benbarclay

Copy link
Copy Markdown
Collaborator

Salvaged and merged. Thanks @austinlaw076 for this work.

The two unique fixes from this PR were cherry-picked (authorship preserved) and merged as #59339 (commit 76979a086):

  • Anthropic OAuth path hijack_HERMES_OAUTH_FILE was frozen at import to the default profile's path, so multiplexed profile turns read/wrote the default profile's .anthropic_oauth.json. Replaced with a lazy _get_hermes_oauth_file() resolver; verified locally that a profile turn now resolves its own home.
  • Port-binding platform setwhatsapp_cloud and line now join _PORT_BINDING_PLATFORM_VALUES so secondary multiplex profiles enabling them fail fast instead of colliding on the listener (both confirmed to bind aiohttp TCP sites).

The remaining parts were not carried because they are already handled on main: the 55-site adapter routing sweep is superseded by #59310, the cron secret scope landed as fdab380a1, and the nested-config fallback / get_env_value rework were covered elsewhere. The credential-isolation issues this PR referenced (#52446, #52307, #52796) are tracked separately.

Closing as superseded by #59339 — the unique, still-needed value from here has shipped.

@benbarclay benbarclay closed this Jul 7, 2026
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…latform set (NousResearch#57563 salvage) (NousResearch#59339)

* fix(auth): resolve Anthropic OAuth file per-profile + close port-binding platform gaps

Two focused pieces salvaged from PR NousResearch#57563:

1. _HERMES_OAUTH_FILE was computed at module import time — frozen before
   HERMES_HOME/profile overrides, so multiplexed profile turns read and
   wrote the DEFAULT profile's .anthropic_oauth.json (OAuth path hijack).
   Replaced with a lazy _get_hermes_oauth_file(); all web_server.py call
   sites updated.

2. _PORT_BINDING_PLATFORM_VALUES was missing whatsapp_cloud and line —
   both bind aiohttp TCP listeners, so a secondary multiplex profile
   enabling them would collide with the primary's listener instead of
   failing fast at startup.

Original work by @austinlaw076. The rest of NousResearch#57563 was redundant on
main (adapter routing sweep superseded by NousResearch#56854's salvage; cron secret
scope landed in ab1b128; nested-config fallback in from_dict).

* chore(release): map austinlaw076 author email for PR NousResearch#57563 salvage

* test(hermes_cli): patch _get_hermes_oauth_file instead of removed _HERMES_OAUTH_FILE constant

---------

Co-authored-by: Austin <austin@openvm067.space>
Co-authored-by: Ben <ben@nousresearch.com>
justemu pushed a commit to justemu/hermes-agent that referenced this pull request Jul 18, 2026
…latform set (NousResearch#57563 salvage) (NousResearch#59339)

* fix(auth): resolve Anthropic OAuth file per-profile + close port-binding platform gaps

Two focused pieces salvaged from PR NousResearch#57563:

1. _HERMES_OAUTH_FILE was computed at module import time — frozen before
   HERMES_HOME/profile overrides, so multiplexed profile turns read and
   wrote the DEFAULT profile's .anthropic_oauth.json (OAuth path hijack).
   Replaced with a lazy _get_hermes_oauth_file(); all web_server.py call
   sites updated.

2. _PORT_BINDING_PLATFORM_VALUES was missing whatsapp_cloud and line —
   both bind aiohttp TCP listeners, so a secondary multiplex profile
   enabling them would collide with the primary's listener instead of
   failing fast at startup.

Original work by @austinlaw076. The rest of NousResearch#57563 was redundant on
main (adapter routing sweep superseded by NousResearch#56854's salvage; cron secret
scope landed in fdab380; nested-config fallback in from_dict).

* chore(release): map austinlaw076 author email for PR NousResearch#57563 salvage

* test(hermes_cli): patch _get_hermes_oauth_file instead of removed _HERMES_OAUTH_FILE constant

---------

Co-authored-by: Austin <austin@openvm067.space>
Co-authored-by: Ben <ben@nousresearch.com>
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…latform set (NousResearch#57563 salvage) (NousResearch#59339)

* fix(auth): resolve Anthropic OAuth file per-profile + close port-binding platform gaps

Two focused pieces salvaged from PR NousResearch#57563:

1. _HERMES_OAUTH_FILE was computed at module import time — frozen before
   HERMES_HOME/profile overrides, so multiplexed profile turns read and
   wrote the DEFAULT profile's .anthropic_oauth.json (OAuth path hijack).
   Replaced with a lazy _get_hermes_oauth_file(); all web_server.py call
   sites updated.

2. _PORT_BINDING_PLATFORM_VALUES was missing whatsapp_cloud and line —
   both bind aiohttp TCP listeners, so a secondary multiplex profile
   enabling them would collide with the primary's listener instead of
   failing fast at startup.

Original work by @austinlaw076. The rest of NousResearch#57563 was redundant on
main (adapter routing sweep superseded by NousResearch#56854's salvage; cron secret
scope landed in fdab380; nested-config fallback in from_dict).

* chore(release): map austinlaw076 author email for PR NousResearch#57563 salvage

* test(hermes_cli): patch _get_hermes_oauth_file instead of removed _HERMES_OAUTH_FILE constant

---------

Co-authored-by: Austin <austin@openvm067.space>
Co-authored-by: Ben <ben@nousresearch.com>
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…latform set (NousResearch#57563 salvage) (NousResearch#59339)

* fix(auth): resolve Anthropic OAuth file per-profile + close port-binding platform gaps

Two focused pieces salvaged from PR NousResearch#57563:

1. _HERMES_OAUTH_FILE was computed at module import time — frozen before
   HERMES_HOME/profile overrides, so multiplexed profile turns read and
   wrote the DEFAULT profile's .anthropic_oauth.json (OAuth path hijack).
   Replaced with a lazy _get_hermes_oauth_file(); all web_server.py call
   sites updated.

2. _PORT_BINDING_PLATFORM_VALUES was missing whatsapp_cloud and line —
   both bind aiohttp TCP listeners, so a secondary multiplex profile
   enabling them would collide with the primary's listener instead of
   failing fast at startup.

Original work by @austinlaw076. The rest of NousResearch#57563 was redundant on
main (adapter routing sweep superseded by NousResearch#56854's salvage; cron secret
scope landed in fdab380; nested-config fallback in from_dict).

* chore(release): map austinlaw076 author email for PR NousResearch#57563 salvage

* test(hermes_cli): patch _get_hermes_oauth_file instead of removed _HERMES_OAUTH_FILE constant

---------

Co-authored-by: Austin <austin@openvm067.space>
Co-authored-by: Ben <ben@nousresearch.com>
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…latform set (NousResearch#57563 salvage) (NousResearch#59339)

* fix(auth): resolve Anthropic OAuth file per-profile + close port-binding platform gaps

Two focused pieces salvaged from PR NousResearch#57563:

1. _HERMES_OAUTH_FILE was computed at module import time — frozen before
   HERMES_HOME/profile overrides, so multiplexed profile turns read and
   wrote the DEFAULT profile's .anthropic_oauth.json (OAuth path hijack).
   Replaced with a lazy _get_hermes_oauth_file(); all web_server.py call
   sites updated.

2. _PORT_BINDING_PLATFORM_VALUES was missing whatsapp_cloud and line —
   both bind aiohttp TCP listeners, so a secondary multiplex profile
   enabling them would collide with the primary's listener instead of
   failing fast at startup.

Original work by @austinlaw076. The rest of NousResearch#57563 was redundant on
main (adapter routing sweep superseded by NousResearch#56854's salvage; cron secret
scope landed in a50bca5; nested-config fallback in from_dict).

* chore(release): map austinlaw076 author email for PR NousResearch#57563 salvage

* test(hermes_cli): patch _get_hermes_oauth_file instead of removed _HERMES_OAUTH_FILE constant

---------

Co-authored-by: Austin <austin@openvm067.space>
Co-authored-by: Ben <ben@nousresearch.com>
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 comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P2 Medium — degraded but workaround exists provider/anthropic Anthropic native Messages API sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/security Security vulnerability or hardening

Projects

None yet

4 participants