hermes - 💡(How to fix) Fix Dashboard WebSocket endpoints (/api/ws, /api/events) return 403 even with --insecure mode

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Dashboard WebSocket endpoints /api/ws and /api/events return 403 Forbidden even when HERMES_DASHBOARD_INSECURE=1 is set. This affects both remote and localhost access. The HTTP pages and REST API work fine — only WebSocket connections are rejected.

Root Cause

The --insecure flag appears to bypass the OAuth auth gate for HTTP requests but the WebSocket endpoint has a separate token verification path that is not affected by the --insecure flag. The frontend obtains a token and passes it as a query parameter, but the backend rejects it regardless.

Code Example

curl -i -N \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  "http://127.0.0.1:9119/api/ws"
RAW_BUFFERClick to expand / collapse

Title:

Dashboard WebSocket endpoints (/api/ws, /api/events) return 403 even with --insecure mode Body:

Description

Dashboard WebSocket endpoints /api/ws and /api/events return 403 Forbidden even when HERMES_DASHBOARD_INSECURE=1 is set. This affects both remote and localhost access. The HTTP pages and REST API work fine — only WebSocket connections are rejected.

Steps to Reproduce

  1. Run hermes-agent with the latest s6-overlay Docker image

  2. Set HERMES_DASHBOARD=1, HERMES_DASHBOARD_HOST=0.0.0.0, HERMES_DASHBOARD_INSECURE=1

  3. Access the dashboard — pages load normally

  4. Observe browser console errors: WebSocket connection to 'ws://<host>:9119/api/ws?token=...' failed WebSocket connection to 'ws://<host>:9119/api/events?token=...' failed

  5. Verify with curl from inside the container against localhost:

curl -i -N \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  "http://127.0.0.1:9119/api/ws"

Returns 403 Forbidden (after fixing the key format, returns 101 only without the token check).

Expected Behavior

When HERMES_DASHBOARD_INSECURE=1 is set, WebSocket endpoints should be accessible without OAuth authentication, same as the HTTP REST API endpoints.

Actual Behavior

HTTP pages: ✅ accessible REST API (/api/status, /api/sessions, etc.): ✅ accessible WebSocket (/api/ws, /api/events): ❌ 403 Forbidden

Impact

Chat tab (TUI in browser) is completely non-functional Real-time event updates don't work Affects all users running dashboard in Docker with --insecure on trusted LANs

Environment

Docker image: nousresearch/hermes-agent:latest (s6-overlay version) OS: UGOS (UGREEN NAS) HERMES_DASHBOARD_INSECURE=1 confirmed working for HTTP Dashboard run script confirms --insecure flag is passed

Analysis

The --insecure flag appears to bypass the OAuth auth gate for HTTP requests but the WebSocket endpoint has a separate token verification path that is not affected by the --insecure flag. The frontend obtains a token and passes it as a query parameter, but the backend rejects it regardless.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix Dashboard WebSocket endpoints (/api/ws, /api/events) return 403 even with --insecure mode