Skip to content

feat(dashboard): HERMES_DASHBOARD_EXTRA_HOSTS for reverse-proxy WS Origin - #70064

Closed
Dbillionaer wants to merge 1 commit into
NousResearch:mainfrom
Dbillionaer:feat/dashboard-extra-hosts
Closed

feat(dashboard): HERMES_DASHBOARD_EXTRA_HOSTS for reverse-proxy WS Origin#70064
Dbillionaer wants to merge 1 commit into
NousResearch:mainfrom
Dbillionaer:feat/dashboard-extra-hosts

Conversation

@Dbillionaer

Copy link
Copy Markdown

Summary

When the Hermes dashboard is bound to loopback (127.0.0.1) and served behind a reverse proxy (nginx → Tailscale Serve, Cloudflare Tunnel, etc.), HTTP pages work because the proxy rewrites the Host header. WebSocket upgrades fail because the browser's Origin header contains the proxy hostname (e.g. srv1480921.tail230ee9.ts.net) while bound_host is 127.0.0.1.

The browser-set Origin is a security header — it cannot be rewritten by the proxy. So every WS endpoint (/api/pty, /api/console, /api/ws) is rejected with:

pty refused: origin_mismatch origin=https://<proxy-host> bound=127.0.0.1

This PR adds HERMES_DASHBOARD_EXTRA_HOSTS — a comma-separated env var of operator-defined trusted hostnames that _is_accepted_host() accepts in addition to the bound host and loopback aliases.

Usage

# systemd unit / env
HERMES_DASHBOARD_EXTRA_HOSTS=srv1480921.tail230ee9.ts.net

For operators with multiple proxy hostnames:

HERMES_DASHBOARD_EXTRA_HOSTS=host1.ts.net,host2.ts.net

Security

All existing security checks remain fully intact:

Check Status
DNS rebinding defense (GHSA-ppp5-vxwm-4cf7) ✅ Non-allowlisted hosts still rejected
Loopback bind ✅ Stays loopback — no public exposure
Auth gate ✅ Non-loopback binds still require OAuth/password
Peer check ✅ Unchanged

Only hostnames the operator explicitly lists are accepted. This is strictly additive — it doesn't widen acceptance for any host not in the list.

Changes

  • hermes_cli/web_server.py: 9-line addition to _is_accepted_host() — checks HERMES_DASHBOARD_EXTRA_HOSTS env var before the existing bound-host validation

Related

Test plan

  • Set HERMES_DASHBOARD_EXTRA_HOSTS=<hostname>, verify WS Origin with that hostname is accepted
  • Verify loopback origins still accepted when env var is set
  • Verify random/evil hostnames still rejected (DNS rebinding defense intact)
  • Verify unset env var = existing behavior (no regression)
  • Verify comma-separated multiple hosts work
  • Verify port suffixes are handled correctly (stripped before comparison)

…igin

When the dashboard is bound to loopback and served behind a reverse
proxy (nginx, Tailscale Serve, Cloudflare Tunnel, etc.), HTTP pages
work because the proxy rewrites the Host header. WebSocket upgrades
fail because the browser Origin header contains the proxy hostname
while bound_host is 127.0.0.1. The browser-set Origin cannot be
rewritten by the proxy.

This adds HERMES_DASHBOARD_EXTRA_HOSTS - a comma-separated env var
of operator-defined trusted hostnames that _is_accepted_host()
accepts in addition to the bound host and loopback aliases.

All existing security checks remain intact (DNS rebinding defense,
auth gate, peer check).

Closes NousResearch#70059. Related: NousResearch#34390, NousResearch#55917.
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/dashboard Web dashboard / control panel UI (dashboard/, landing) area/config Config system, migrations, profiles needs-decision Awaiting maintainer decision before any implementation 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 23, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #42344 and #68251 use the existing dashboard.public_url as the trust source, while this PR adds a separate comma-separated hostname allowlist. Both address proxy-origin acceptance, but selecting the intended configuration contract needs a maintainer decision.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for isolating a real reverse-proxy WebSocket failure. Current main still routes both HTTP Host validation and WebSocket Origin validation through _is_accepted_host() (hermes_cli/web_server.py:525, hermes_cli/web_server.py:14371).

  • This PR's user-facing solution is the new HERMES_DASHBOARD_EXTRA_HOSTS setting (6f897d0f7e24, hermes_cli/web_server.py). The repository policy requires non-secret behavioral settings to live in config.yaml, not new HERMES_* environment variables (AGENTS.md:102-106).
  • Please re-scope any follow-up around a dashboard config setting with exact-match validation and regression coverage for both the HTTP middleware and WebSocket Host/Origin paths.
  • The related discussion correctly identifies competing dashboard.public_url and config-based contracts; selecting the final configuration contract remains a maintainer decision.

This is an automated hermes-sweeper review.


Closed as not-planned per standing maintainer policy (env-var-for-config). This is a design-direction decision, not a code-quality judgment — see the Contribution Rubric in AGENTS.md for what the project is looking for. If you believe this policy was misapplied to your change, comment here and a maintainer will take a look.

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/dashboard Web dashboard / control panel UI (dashboard/, landing) needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard: add HERMES_DASHBOARD_EXTRA_HOSTS for reverse-proxy / Tailscale WS Origin acceptance

3 participants