Fix(gateway/cron): resolve BWS multiplexing credential isolation, OAuth path hijack, and cron scheduler thread safety - #57563
Conversation
… dynamic home resolution
Related: #56302 (OPEN — fixes the SAME import-time-freeze of the Anthropic OAuth file path in |
|
suggesting changes Security evidence:
Please change the secondary-profile path so |
Hey @egilewski, thanks for the review! I’ve just updated the PR branch with the following changes:
Mind taking another look? Thanks! |
…lution # Conflicts: # cron/scheduler.py
|
suggesting changes Security evidence:
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 |
…d cron, telegram, and continuity plugin modifications
|
│ Hi @egilewski, thanks for pointing out the scope |
…ides in multiplex mode
…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.
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.
…for_source Reviewer audit found LOW-severity docstring typo where the helper's docstring referenced itself instead of the old self.adapters.get() pattern.
…ne send token leaks
|
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 Please make Signed: GPT-5.5-xhigh in Codex |
…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).
…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>
|
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
The remaining parts were not carried because they are already handled on Closing as superseded by #59339 — the unique, still-needed value from here has shipped. |
…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>
…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>
…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>
…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>
…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>
This PR fixes critical multiplex_profiles logic flaws, BWS/OAuth credential leakage, cron scheduler thread safety, and profile-aware adapter routing.
Key fixes:
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.