Skip to content

fix: compare base-URL hostnames, not substrings, in provider-identity checks - #85737

Merged
teknium1 merged 1 commit into
mainfrom
pi-port/base-url-host-identity
Aug 15, 2026
Merged

teknium1 merged 1 commit into
mainfrom
pi-port/base-url-host-identity

Conversation

@teknium1

Copy link
Copy Markdown
Collaborator

Summary

Provider-identity checks now compare base-URL hostnames instead of raw substrings, so proxy URLs with a provider host in their path, lookalike domains, and case variants no longer misroute credentials, catalogs, or cache layout.

Port of the bug class from earendil-works/pi#7933 ("detect DeepSeek base URLs case-insensitively" — their substring check missed case variants and matched lookalike URLs). Hermes had the identical class at five sites that utils.base_url_host_matches() / base_url_hostname() were built for but never migrated onto.

Changes

  • hermes_cli/cli_agent_setup_mixin.py: keyless-custom-endpoint detection (2 sites) — "openrouter.ai" not in base_url treated https://proxy.internal/openrouter.ai/v1 and https://openrouter.ai.evil.com as OpenRouter (blocking keyless local use) and treated https://OpenRouter.AI as a keyless custom endpoint (silently sending a placeholder key to real OpenRouter).
  • hermes_cli/models.py validate_requested_model: same substring check deciding openrouter-vs-custom catalog routing for /model validation.
  • hermes_cli/runtime_provider.py: local-model autodetect fired for any URL containing localhost/127.0.0.1 — including remote hostnames that merely contain the string.
  • gateway/run.py: /status endpoint display, same local-host substring.
  • agent/agent_runtime_helpers.py: Nous Portal cache-layout detection matched nousresearch anywhere in the URL.
  • tests/hermes_cli/test_base_url_host_identity.py: regression tests for the class (proxy-path, lookalike-domain, case-variant, local-host cases).

Validation

Before After
https://proxy.internal/openrouter.ai/v1, no key treated as OpenRouter → not ready keyless custom endpoint → ready
https://OpenRouter.AI/api/v1, no key keyless custom → placeholder key sent recognized as OpenRouter → onboarding
new regression tests vs old predicate (sabotage run) 3 fail 8/8 pass
tests/cli/test_cli_first_run_setup.py + tests/agent/test_nous_portal_anthropic_wire.py + test_prompt_cache_boundary.py — 56 passed

Weekly Pi scout cron; opened for review, not merged.

Infographic

Hostname, not substring

… checks

Port of the bug class from earendil-works/pi#7933 (DeepSeek base-URL
detection matched by raw substring, missing case variants and matching
lookalike URLs). Hermes had the same class at five sites:

- cli_agent_setup_mixin.py: keyless-custom-endpoint detection treated any
  URL containing the OpenRouter host substring (path segment, lookalike
  domain) as OpenRouter, and missed case variants of the real host.
- models.py validate_requested_model: same substring check for routing an
  openrouter provider with a custom base_url to the custom catalog.
- runtime_provider.py: local-endpoint autodetect matched the string
  localhost anywhere in the URL, including remote hostnames containing it.
- gateway/run.py: /status endpoint display, same local-host substring.
- agent_runtime_helpers.py: Nous Portal cache-layout detection matched
  the nousresearch substring anywhere in the URL.

All sites now use the existing base_url_host_matches / base_url_hostname
helpers (exact host or subdomain, case-insensitive). Regression tests
proven to fail against the old predicates.
@github-actions

github-actions Bot commented Aug 14, 2026 •

Copy link
Copy Markdown

૮ >ﻌ< ა ci review

ran on 82763e9 — fix: compare base-URL hostnames, not substrings, in provider

⚠️ Warnings

OSV vulnerability scan · View job

5 known vulnerabilities found in pinned dependencies.

How to fix:

Review the findings in the Security tab. Update the affected dependencies if a patched version is available.


debug info

CI timings

CI timings · View report · View job

Wall time 3m18s vs 6m49s (-51.6%). 11 job(s) slower, 9 faster, 4 unchanged.

  • Python tests / Run tests slice 2/12: +49.0s
  • Python tests / Run tests slice 6/12: -40.0s
  • Python tests / Run tests slice 11/12: -32.0s
  • Python tests / Run tests slice 8/12: +27.0s
  • Python tests / Run tests slice 10/12: +17.0s

@alt-glitch alt-glitch added type/bug Something isn't working P0 Critical — data loss, security, crash loop 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/portal Nous portal / Hermes Pro / hosted-Hermes path provider/openrouter OpenRouter aggregator area/config Config system, migrations, profiles sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 14, 2026
@teknium1
teknium1 merged commit bc5805c into main Aug 15, 2026
48 checks passed
@teknium1
teknium1 deleted the pi-port/base-url-host-identity branch August 15, 2026 03:47
teknium1 added a commit that referenced this pull request Aug 15, 2026
Follow-up to #85737, which migrated five provider-identity sites onto
utils.base_url_host_matches()/base_url_hostname(). This completes the class
sweep (never-patch-predicates: one owner, every site) and folds in the two
open contributor PRs attacking individual sites:

- agent/auxiliary_client.py ZAI/Kimi OpenAI-wire rewrite (PR #85715,
  pierrenode): 'bigmodel'/'api.z.ai'/'api.kimi.com' substring checks
  rewrote proxy paths containing those markers.
- hermes_cli/runtime_provider.py Azure endpoint detection (PR #74721,
  RelaxJonh, issue #74312): 'azure.com' substring picked the Azure key
  for non-Azure hosts whose path contained the text.
- run_agent.py: _is_azure_openai_url, _is_copilot_url, Anthropic
  credential-refresh azure guard, _anthropic_preserve_dots host
  allowlist, OpenRouter/mistral reasoning gates.
- agent/chat_completion_helpers.py: nousresearch / nvidia detection.
- agent/conversation_loop.py: GitHub Models 413 hint.
- agent/usage_pricing.py: localhost billing-route detection.
- hermes_cli/model_switch.py: api.openai.com catalog fallback and
  localhost custom-provider detection.
- cli.py: local-model autodetect and Ollama/LM Studio context-length
  hints (port-anchored instead of '11434' in URL).
- tools/mcp_oauth.py: Figma remote-MCP detection.
- tools/skills_hub.py: raw.githubusercontent.com source-URL check.

Regression tests extend tests/hermes_cli/test_base_url_host_identity.py
(azure/copilot/dotted-model/figma proxy-path + lookalike cases) and
tests/agent/test_minimax_auxiliary_url.py (ZAI/Kimi path false positives).

Closes #74312. Salvages #85715 and #74721 with authorship preserved.
RickyYii added a commit to RickyYii/hermes-agent that referenced this pull request Aug 17, 2026
Resolves the only conflict: NousResearch#85737's follow-up (4b7b2b0) added
`from utils import base_url_host_matches, base_url_hostname` at the same
import site where this branch added `base_url_origin`. Both are wanted —
upstream's two symbols back the widened hostname-identity sweep, and
`base_url_origin` backs the alias credential-reuse origin check — so the
import is merged rather than either side dropped.

No other file conflicted. Verified after the merge: the alias credential
matrix is unchanged (8/8), this branch's 46 cases pass, and upstream's new
tests/hermes_cli/test_base_url_host_identity.py passes (13).
bobaba76 pushed a commit to bobaba76/hermes-agent that referenced this pull request Aug 27, 2026
Follow-up to NousResearch#85737, which migrated five provider-identity sites onto
utils.base_url_host_matches()/base_url_hostname(). This completes the class
sweep (never-patch-predicates: one owner, every site) and folds in the two
open contributor PRs attacking individual sites:

- agent/auxiliary_client.py ZAI/Kimi OpenAI-wire rewrite (PR NousResearch#85715,
  pierrenode): 'bigmodel'/'api.z.ai'/'api.kimi.com' substring checks
  rewrote proxy paths containing those markers.
- hermes_cli/runtime_provider.py Azure endpoint detection (PR NousResearch#74721,
  RelaxJonh, issue NousResearch#74312): 'azure.com' substring picked the Azure key
  for non-Azure hosts whose path contained the text.
- run_agent.py: _is_azure_openai_url, _is_copilot_url, Anthropic
  credential-refresh azure guard, _anthropic_preserve_dots host
  allowlist, OpenRouter/mistral reasoning gates.
- agent/chat_completion_helpers.py: nousresearch / nvidia detection.
- agent/conversation_loop.py: GitHub Models 413 hint.
- agent/usage_pricing.py: localhost billing-route detection.
- hermes_cli/model_switch.py: api.openai.com catalog fallback and
  localhost custom-provider detection.
- cli.py: local-model autodetect and Ollama/LM Studio context-length
  hints (port-anchored instead of '11434' in URL).
- tools/mcp_oauth.py: Figma remote-MCP detection.
- tools/skills_hub.py: raw.githubusercontent.com source-URL check.

Regression tests extend tests/hermes_cli/test_base_url_host_identity.py
(azure/copilot/dotted-model/figma proxy-path + lookalike cases) and
tests/agent/test_minimax_auxiliary_url.py (ZAI/Kimi path false positives).

Closes NousResearch#74312. Salvages NousResearch#85715 and NousResearch#74721 with authorship preserved.
melon-xf added a commit to melon-xf/hermes-agent that referenced this pull request Sep 3, 2026
Follow-up to NousResearch#85737, which migrated five provider-identity sites onto
utils.base_url_host_matches()/base_url_hostname(). This completes the class
sweep (never-patch-predicates: one owner, every site) and folds in the two
open contributor PRs attacking individual sites:

- agent/auxiliary_client.py ZAI/Kimi OpenAI-wire rewrite (PR NousResearch#85715,
  pierrenode): 'bigmodel'/'api.z.ai'/'api.kimi.com' substring checks
  rewrote proxy paths containing those markers.
- hermes_cli/runtime_provider.py Azure endpoint detection (PR NousResearch#74721,
  RelaxJonh, issue NousResearch#74312): 'azure.com' substring picked the Azure key
  for non-Azure hosts whose path contained the text.
- run_agent.py: _is_azure_openai_url, _is_copilot_url, Anthropic
  credential-refresh azure guard, _anthropic_preserve_dots host
  allowlist, OpenRouter/mistral reasoning gates.
- agent/chat_completion_helpers.py: nousresearch / nvidia detection.
- agent/conversation_loop.py: GitHub Models 413 hint.
- agent/usage_pricing.py: localhost billing-route detection.
- hermes_cli/model_switch.py: api.openai.com catalog fallback and
  localhost custom-provider detection.
- cli.py: local-model autodetect and Ollama/LM Studio context-length
  hints (port-anchored instead of '11434' in URL).
- tools/mcp_oauth.py: Figma remote-MCP detection.
- tools/skills_hub.py: raw.githubusercontent.com source-URL check.

Regression tests extend tests/hermes_cli/test_base_url_host_identity.py
(azure/copilot/dotted-model/figma proxy-path + lookalike cases) and
tests/agent/test_minimax_auxiliary_url.py (ZAI/Kimi path false positives).

Closes NousResearch#74312. Salvages NousResearch#85715 and NousResearch#74721 with authorship preserved.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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/portal Nous portal / Hermes Pro / hosted-Hermes path P0 Critical — data loss, security, crash loop provider/openrouter OpenRouter aggregator sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) 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 type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants