fix(dashboard): allow chat websockets on insecure public bind#33278
fix(dashboard): allow chat websockets on insecure public bind#33278SeaXen wants to merge 1 commit into
Conversation
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.
|
Looks like this is already covered by #18633, which was merged on 2026-05-02. That PR fixed the same root cause:
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 |
|
Correction / nuance after checking current
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:
So this is not just a false report — the breakage is real on current |
|
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 dashboard --host 0.0.0.0 --port 9119 --insecure --tui --no-openObserved behaviorOpening the dashboard locally works: Opening the same dashboard from another LAN device also loads the HTTP shell: …but the embedded Chat/TUI immediately shows: 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 Local root causeIn app.state.auth_requiredis true. But in the common LAN/self-hosted command: hermes dashboard --host 0.0.0.0 --port 9119 --insecure --tui --no-open
Auth noteI 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 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:
Expected behaviorWhen the operator explicitly starts the dashboard with: hermes dashboard --host 0.0.0.0 --port 9119 --insecure --tui --no-openthen dashboard Chat/TUI WebSockets should either:
The current behavior — dashboard loads but Chat only shows This PR’s approach seems aligned with the expected behavior for the |
Summary
--host 0.0.0.0/:: --insecure/chatbreakage where the HTML shell loaded but/api/wsand/api/eventswere rejected with HTTP 403Root cause
The dashboard treated insecure wildcard bind like loopback mode for websocket peer admission. That made LAN browsers load
/chatsuccessfully but fail the live websocket/event feeds, leaving the embedded TUI chat disconnected.Verification
/usr/local/lib/hermes-agent/venv/bin/python -m pytest /usr/local/lib/hermes-agent/tests/hermes_cli/test_dashboard_auth_ws_auth.py -qhttp://192.168.0.222:9120/chat/api/ws/api/events