Skip to content

fix(dashboard-auth): warn when public_url override is silently rejected (#42780)#43214

Merged
benbarclay merged 1 commit into
mainfrom
fix/dashboard-public-url-warn-malformed
Jun 10, 2026
Merged

fix(dashboard-auth): warn when public_url override is silently rejected (#42780)#43214
benbarclay merged 1 commit into
mainfrom
fix/dashboard-public-url-warn-malformed

Conversation

@benbarclay

Copy link
Copy Markdown
Collaborator

Problem

resolve_public_url() runs every operator-supplied HERMES_DASHBOARD_PUBLIC_URL / dashboard.public_url value through _normalise_public_url(), which returns "" for anything that isn't a valid http(s)://host[/path]. By design "" is indistinguishable from "unset", so the caller silently falls back to reconstructing the OAuth redirect_uri from request headers.

The overwhelmingly common trip-wire is a missing scheme — an operator sets HERMES_DASHBOARD_PUBLIC_URL=hermes.domain.com (no https://). The value is dropped without a peep, and behind a reverse proxy that doesn't forward X-Forwarded-Proto reliably, the dashboard then generates an http:// callback even though the operator explicitly declared the public URL. There is currently no log line telling them why their setting had no effect.

This is the most likely root cause of #42780 (env var set, callback still http://, only fixed by setting dashboard.public_url in config.yaml — presumably written with the scheme there).

Fix

Emit a deduplicated operator-facing WARNING when a non-empty value is rejected, naming the offending value and the required scheme:

WARNING HERMES_DASHBOARD_PUBLIC_URL env var is set to 'hermes.domain.com' but was
ignored because it is not a valid absolute URL — it must include an http:// or
https:// scheme (e.g. https://hermes.domain.com). Falling back to reconstructing
the OAuth redirect URI from request headers, which may produce the wrong scheme
behind a reverse proxy.

Dedup is keyed on (source, value) because resolve_public_url() runs per request — without it a misconfigured deploy would flood the logs. Behaviour is otherwise unchanged: malformed values are still rejected, valid values still pass through.

Tests

tests/hermes_cli/test_dashboard_auth_prefix.py:

  • test_scheme_less_public_url_env_warns_operator — scheme-less value emits the warning
  • test_scheme_less_public_url_warning_is_deduplicated — fires at most once across 5 calls
  • test_valid_public_url_emits_no_warning — no spurious warning for a valid value

All three fail without the source change (verified by reverting prefix.py and re-running). Full prefix suite: 22 passed.

Scope

Pure dashboard-auth config-resolution behaviour (container/reverse-proxy deploys). Does not change the redirect-URI construction itself — complementary to #42937, which addresses the separate Tier-2/3 (no public_url set) scheme-mismatch path.

A non-empty HERMES_DASHBOARD_PUBLIC_URL / dashboard.public_url value that
fails URL validation (overwhelmingly: a missing http(s):// scheme, e.g.
"hermes.domain.com") was silently discarded by resolve_public_url(),
falling back to reconstructing the OAuth redirect_uri from request
headers. Behind a reverse proxy that doesn't forward X-Forwarded-Proto
reliably, that yields an http:// callback even though the operator
explicitly set the public URL — with no signal as to why (#42780).

Emit a deduplicated operator-facing WARNING (once per distinct value,
since resolve_public_url runs per request) naming the offending value
and the required scheme. Turns a silent footgun into a self-diagnosing
one; behaviour is otherwise unchanged.

Tests assert the warning fires for a scheme-less value, is deduplicated
across repeated calls, and stays silent for a valid value — all three
fail without the fix.
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: fix/dashboard-public-url-warn-malformed vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10620 on HEAD, 10620 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5564 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have area/auth Authentication, OAuth, credential pools comp/cli CLI entry point, hermes_cli/, setup wizard labels Jun 10, 2026
@benbarclay benbarclay merged commit 7df3aa3 into main Jun 10, 2026
23 checks passed
@benbarclay benbarclay deleted the fix/dashboard-public-url-warn-malformed branch June 10, 2026 02:14

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

Looks Good

  • Clean fix: warn when HERMES_DASHBOARD_PUBLIC_URL is set but invalid or being silently rejected.
  • Adds explicit warning rather than silently ignoring the misconfiguration, improving debuggability.
  • 2 files changed, focused on dashboard auth.
  • No security concerns - this is a warning improvement.

Reviewed by Hermes Agent

wachoo pushed a commit to wachoo/hermes-agent that referenced this pull request Jun 10, 2026
…ed (NousResearch#43214)

A non-empty HERMES_DASHBOARD_PUBLIC_URL / dashboard.public_url value that
fails URL validation (overwhelmingly: a missing http(s):// scheme, e.g.
"hermes.domain.com") was silently discarded by resolve_public_url(),
falling back to reconstructing the OAuth redirect_uri from request
headers. Behind a reverse proxy that doesn't forward X-Forwarded-Proto
reliably, that yields an http:// callback even though the operator
explicitly set the public URL — with no signal as to why (NousResearch#42780).

Emit a deduplicated operator-facing WARNING (once per distinct value,
since resolve_public_url runs per request) naming the offending value
and the required scheme. Turns a silent footgun into a self-diagnosing
one; behaviour is otherwise unchanged.

Tests assert the warning fires for a scheme-less value, is deduplicated
across repeated calls, and stays silent for a valid value — all three
fail without the fix.
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
…ed (NousResearch#43214)

A non-empty HERMES_DASHBOARD_PUBLIC_URL / dashboard.public_url value that
fails URL validation (overwhelmingly: a missing http(s):// scheme, e.g.
"hermes.domain.com") was silently discarded by resolve_public_url(),
falling back to reconstructing the OAuth redirect_uri from request
headers. Behind a reverse proxy that doesn't forward X-Forwarded-Proto
reliably, that yields an http:// callback even though the operator
explicitly set the public URL — with no signal as to why (NousResearch#42780).

Emit a deduplicated operator-facing WARNING (once per distinct value,
since resolve_public_url runs per request) naming the offending value
and the required scheme. Turns a silent footgun into a self-diagnosing
one; behaviour is otherwise unchanged.

Tests assert the warning fires for a scheme-less value, is deduplicated
across repeated calls, and stays silent for a valid value — all three
fail without the fix.
alt-glitch pushed a commit that referenced this pull request Jun 14, 2026
…ed (#43214)

A non-empty HERMES_DASHBOARD_PUBLIC_URL / dashboard.public_url value that
fails URL validation (overwhelmingly: a missing http(s):// scheme, e.g.
"hermes.domain.com") was silently discarded by resolve_public_url(),
falling back to reconstructing the OAuth redirect_uri from request
headers. Behind a reverse proxy that doesn't forward X-Forwarded-Proto
reliably, that yields an http:// callback even though the operator
explicitly set the public URL — with no signal as to why (#42780).

Emit a deduplicated operator-facing WARNING (once per distinct value,
since resolve_public_url runs per request) naming the offending value
and the required scheme. Turns a silent footgun into a self-diagnosing
one; behaviour is otherwise unchanged.

Tests assert the warning fires for a scheme-less value, is deduplicated
across repeated calls, and stays silent for a valid value — all three
fail without the fix.
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 comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants