Bug Description
When running hermes dashboard --host 0.0.0.0 --insecure --tui and accessing the dashboard from another host on the local network, the TUI interface never loads. The page appears but stays blank/stuck indefinitely. The WebSocket connection is silently rejected server-side for any non-loopback client IP, even when --insecure is explicitly passed.
Steps to Reproduce
-
Start the dashboard bound to all interfaces:
hermes dashboard --host 0.0.0.0 --insecure --tui
-
Open the dashboard URL from a second machine on the same LAN (non-loopback IP).
-
Observe that the TUI never initializes, HTTP loads, WebSocket does not.
Expected Behavior
When --insecure is passed together with --host 0.0.0.0, WebSocket connections from non-loopback LAN clients should be accepted, consistent with the intent of the --insecure flag.
Actual Behavior
The WebSocket handshake is rejected for any non-loopback client.host. The TUI stays blank. No error is shown to the user, the connection is dropped silently.
Affected Component
Configuration (config.yaml, .env, hermes setup)
Messaging Platform (if gateway-related)
N/A (CLI only)
Debug Report
Operating System
Ubuntu 24.04
Python Version
3.14.3
Hermes Version
v0.14.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
_ws_client_is_allowed() in hermes_cli/web_server.py (~line 3325) unconditionally blocks non-loopback IPs:
pythondef _ws_client_is_allowed(ws: "WebSocket") -> bool:
client_host = ws.client.host if ws.client else ""
if not client_host:
return True
return client_host in _LOOPBACK_HOSTS
start_server() receives allow_public from the --insecure flag but never writes it to app.state, so _ws_client_is_allowed cannot read it.
Proposed Fix (optional)
Two minimal changes to hermes_cli/web_server.py:
- In start_server(), persist allow_public on app.state directly after the existing bound_host/bound_port assignments (~line 4718):
pythonapp.state.bound_host = host
app.state.bound_port = port
**app.state.allow_public = allow_public # add this**
- Extend _ws_client_is_allowed() to respect --insecure:
pythondef _ws_client_is_allowed(ws: "WebSocket") -> bool:
"""Allows loopback clients only, unless --insecure made the server public."""
if getattr(app.state, "allow_public", False):
return True
client_host = ws.client.host if ws.client else ""
if not client_host:
return True
return client_host in _LOOPBACK_HOSTS
Are you willing to submit a PR for this?
Bug Description
When running hermes dashboard --host 0.0.0.0 --insecure --tui and accessing the dashboard from another host on the local network, the TUI interface never loads. The page appears but stays blank/stuck indefinitely. The WebSocket connection is silently rejected server-side for any non-loopback client IP, even when --insecure is explicitly passed.
Steps to Reproduce
Start the dashboard bound to all interfaces:
hermes dashboard --host 0.0.0.0 --insecure --tui
Open the dashboard URL from a second machine on the same LAN (non-loopback IP).
Observe that the TUI never initializes, HTTP loads, WebSocket does not.
Expected Behavior
When --insecure is passed together with --host 0.0.0.0, WebSocket connections from non-loopback LAN clients should be accepted, consistent with the intent of the --insecure flag.
Actual Behavior
The WebSocket handshake is rejected for any non-loopback client.host. The TUI stays blank. No error is shown to the user, the connection is dropped silently.
Affected Component
Configuration (config.yaml, .env, hermes setup)
Messaging Platform (if gateway-related)
N/A (CLI only)
Debug Report
-\-Operating System
Ubuntu 24.04
Python Version
3.14.3
Hermes Version
v0.14.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
_ws_client_is_allowed() in hermes_cli/web_server.py (~line 3325) unconditionally blocks non-loopback IPs:
start_server() receives allow_public from the --insecure flag but never writes it to app.state, so _ws_client_is_allowed cannot read it.
Proposed Fix (optional)
Two minimal changes to hermes_cli/web_server.py:
Are you willing to submit a PR for this?