Skip to content

fix(dashboard): allow chat websockets on insecure public bind#33278

Closed
SeaXen wants to merge 1 commit into
NousResearch:mainfrom
SeaXen:fix/dashboard-insecure-bind-chat-ws
Closed

fix(dashboard): allow chat websockets on insecure public bind#33278
SeaXen wants to merge 1 commit into
NousResearch:mainfrom
SeaXen:fix/dashboard-insecure-bind-chat-ws

Conversation

@SeaXen

@SeaXen SeaXen commented May 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • allow non-loopback websocket peers when the dashboard is explicitly exposed with --host 0.0.0.0/:: --insecure
  • keep the existing loopback-only behavior for loopback binds
  • add regression coverage for the LAN/public /chat breakage where the HTML shell loaded but /api/ws and /api/events were rejected with HTTP 403

Root cause

The dashboard treated insecure wildcard bind like loopback mode for websocket peer admission. That made LAN browsers load /chat successfully but fail the live websocket/event feeds, leaving the embedded TUI chat disconnected.

Verification

  • targeted pytest passes
    • /usr/local/lib/hermes-agent/venv/bin/python -m pytest /usr/local/lib/hermes-agent/tests/hermes_cli/test_dashboard_auth_ws_auth.py -q
  • live regression previously reproduced on http://192.168.0.222:9120/chat
  • LAN websocket opens after fix for both:
    • /api/ws
    • /api/events

Allow non-loopback websocket peers when the dashboard is explicitly exposed with --host 0.0.0.0/:: and --insecure.

This fixes the failure mode where /chat rendered over LAN but /api/ws and /api/events were rejected with HTTP 403, leaving the embedded TUI chat disconnected.

Add regression coverage for the insecure public bind case in the dashboard websocket auth tests.
@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists labels May 27, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competes with open #32614 (same fix — allow WS clients on non-loopback/insecure binds). Also overlaps #25072 (broader 3-bug fix) and #31779 (--insecure propagation). See #32615 for the user report.

@SeaXen

SeaXen commented May 27, 2026

Copy link
Copy Markdown
Contributor Author

Looks like this is already covered by #18633, which was merged on 2026-05-02.

That PR fixed the same root cause:

  • hermes dashboard --host 0.0.0.0 --insecure
  • /chat shell loads
  • /api/ws / /api/events fail for non-loopback peers
  • embedded chat shows events feed disconnected

So this PR is effectively a duplicate of the already-merged fix, though it does add a focused regression test around the insecure public bind case.

Reference: #18633

@SeaXen

SeaXen commented May 27, 2026

Copy link
Copy Markdown
Contributor Author

Correction / nuance after checking current origin/main:

#18633 did fix this previously, but the current main branch no longer contains that bound_host in {"0.0.0.0", "::"} allowance inside _ws_client_is_allowed().

So the bug appears to have regressed later (or that earlier fix was lost in a subsequent refactor), which explains why this was reproducible again on current builds.

In other words:

  • #18633 = prior fix / precedent
  • #33278 = reintroduces that behavior on current main and adds focused regression coverage

So this is not just a false report — the breakage is real on current main.

@tarkilhk

Copy link
Copy Markdown

Thanks — this looks like the right fix for the LAN dashboard case. I can confirm this reproduces on a self-hosted LAN setup.

Environment

  • Hermes Agent: v0.14.0 (2026.5.16)
  • Local repo commit: 78be458608cc
  • Python: 3.11.15
  • OS: Ubuntu/Linux, kernel 6.8.0-117-generic
  • Dashboard command:
hermes dashboard --host 0.0.0.0 --port 9119 --insecure --tui --no-open

Observed behavior

Opening the dashboard locally works:

http://127.0.0.1:9119/chat

Opening the same dashboard from another LAN device also loads the HTTP shell:

http://<host>:9119/chat

…but the embedded Chat/TUI immediately shows:

[session ended]

The dashboard service is healthy and active. HTTP endpoints work. The failure appears isolated to the dashboard WebSocket path used by Chat/TUI.

A loopback reverse proxy workaround confirms the root cause: when Hermes sees the WebSocket peer as 127.0.0.1, Chat works; when Hermes sees the real LAN client IP, Chat fails.

Local root cause

In hermes_cli/web_server.py, _ws_client_is_allowed() allows non-loopback WebSocket clients only when:

app.state.auth_required

is true.

But in the common LAN/self-hosted command:

hermes dashboard --host 0.0.0.0 --port 9119 --insecure --tui --no-open

auth_required is false because --insecure explicitly skips the OAuth auth gate. The result is a split-brain state:

  • HTTP dashboard is intentionally LAN-accessible.
  • Chat/TUI WebSockets remain localhost-only.
  • The UI only shows [session ended], with no clear explanation or recovery action.

Auth note

I also investigated whether enabling dashboard auth would be a clean workaround. It should bypass the peer-IP check in principle, because authenticated dashboard mode sets auth_required = true.

However, the currently bundled dashboard auth provider appears to be Nous Portal OAuth, not local auth. For a private homelab/LAN deployment, requiring a Nous Portal-provisioned dashboard OAuth client is not a practical replacement for either:

  • --insecure on a trusted LAN, or
  • a future local password/token auth mode.

Expected behavior

When the operator explicitly starts the dashboard with:

hermes dashboard --host 0.0.0.0 --port 9119 --insecure --tui --no-open

then dashboard Chat/TUI WebSockets should either:

  1. work from LAN clients, consistent with the public HTTP bind, or
  2. fail with a clear UI/server message explaining that Chat is localhost-only unless OAuth-gated, plus suggested supported access methods.

The current behavior — dashboard loads but Chat only shows [session ended] — looks broken and is hard to diagnose.

This PR’s approach seems aligned with the expected behavior for the --insecure LAN case.

@teknium1

Copy link
Copy Markdown
Contributor

Merged via #35141. Your fix was cherry-picked onto current main with your authorship preserved in git log (commit 6f0523d, on main as part of 17103a1). Added an AUTHOR_MAP entry and kept your Host/Origin-aware regression test as-is. Thanks for the clean fix and test!

@teknium1 teknium1 closed this May 30, 2026
sradetzky pushed a commit to sradetzky/hermes-agent that referenced this pull request May 30, 2026
KKT-OPT pushed a commit to KKT-OPT/hermes-agent that referenced this pull request May 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants