Skip to content

fix(cli): honor --insecure for dashboard WebSocket connections#17887

Closed
ycros wants to merge 1 commit into
NousResearch:mainfrom
ycros:fix/dashboard-ws-public-bind
Closed

fix(cli): honor --insecure for dashboard WebSocket connections#17887
ycros wants to merge 1 commit into
NousResearch:mainfrom
ycros:fix/dashboard-ws-public-bind

Conversation

@ycros

@ycros ycros commented Apr 30, 2026

Copy link
Copy Markdown

Problem

When the dashboard is started with --insecure on a non-loopback bind (e.g. 0.0.0.0), HTTP requests from remote clients are accepted as expected, but WebSocket connections are unconditionally rejected with a 4403 close code. This breaks reverse-proxied or Tailscale-based access where the dashboard needs to be reachable from non-loopback addresses.

What changed

  • _is_accepted_ws_client(ws): new helper that checks app.state.allow_public before applying the loopback defense-in-depth check. When the operator explicitly passed --insecure on a non-loopback bind, remote WebSocket peers are now accepted.
  • _build_sidecar_url(): normalize 0.0.0.0127.0.0.1 and ::::1 when building the PTY sidecar URL, so the spawned chat process can still reach the dashboard's pub endpoint even when bound to all interfaces.
  • start_server(): set app.state.allow_public when --insecure is combined with a non-loopback host.
  • Tests: added tests/hermes_cli/test_web_server_ws_security.py covering:
    • loopback acceptance by default
    • non-loopback rejection when allow_public=False
    • non-loopback acceptance when allow_public=True
    • 0.0.0.0 / :: normalization in _build_sidecar_url()
    • end-to-end WebSocket endpoint behavior via TestClient

Security posture

Default behavior is unchanged: loopback-only binds still reject non-loopback WebSocket clients. The only change is that --insecure (already an explicit operator opt-in for HTTP) now consistently applies to WebSockets as well.

How to test

# Start dashboard on all interfaces with --insecure
hermes web --host 0.0.0.0 --port 9119 --insecure

# From a remote machine (or same machine with 127.0.0.1 replaced by LAN IP):
# Open the dashboard in a browser → Chat tab should connect successfully.
# Before this fix, the WebSocket would close with 4403.

Run the new tests:

pytest tests/hermes_cli/test_web_server_ws_security.py -v

Platforms tested

  • Linux (local)

Use-case: this was originally needed to expose the dashboard over Tailscale to a home LAN, and to make it work behind a Caddy/nginx reverse proxy with basic auth.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard labels Apr 30, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #17440 — both fix WebSocket rejection when --insecure is used on non-loopback binds. This PR adds additional sidecar URL normalization and tests.

@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #17440 — both fix WebSocket rejection when --insecure is used on non-loopback binds.

@ycros ycros marked this pull request as ready for review April 30, 2026 10:17
@ycros

ycros commented Apr 30, 2026

Copy link
Copy Markdown
Author

yup, my agent was over-eager and just created the PR before I had done my own review - I wasn't aware of the other PR, I don't think it existed when I did the fix a day or so ago

Dashboard WebSocket endpoints unconditionally rejected non-loopback
peers even when the operator explicitly started the server with
--insecure on a public bind. This broke reverse-proxied and Tailscale
access, since HTTP honored --insecure but WebSockets did not.

Changes:
- _is_accepted_ws_client(): new helper that respects app.state.allow_public
- _build_sidecar_url(): normalize 0.0.0.0 / :: to loopback for the PTY
  sidecar URL so it remains reachable
- start_server(): set app.state.allow_public when --insecure + non-loopback
- Update docstrings to reflect the new behavior
@ycros

ycros commented May 6, 2026

Copy link
Copy Markdown
Author

I guess this was fixed by some other commit.

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.

2 participants