fix(dashboard): validate WebSocket Host and Origin (salvage #30221) - #31685
Merged
Merged
Conversation
4 tasks
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
unresolved-import |
1 |
First entries
tests/hermes_cli/test_web_server_host_header.py:179: [unresolved-import] unresolved-import: Cannot resolve imported module `starlette.websockets`
✅ Fixed issues: none
Unchanged: 4835 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Salvage of #30221 by @Hinotoi-agent onto current main. CI on the original was failing on a 95-commit-stale branch (kanban_notify flakes + teardown noise); fresh rebase against current main: 199 web_server/dashboard tests pass.
Summary
FastAPI HTTP middleware doesn't run for WebSocket routes, so the existing GHSA-ppp5-vxwm-4cf7 Host-header DNS-rebinding guard was only applied to HTTP. WS upgrades had to be hit too — otherwise a victim browser on the dashboard host could be reached via DNS rebinding + a malicious site, opening ws:// to the loopback dashboard with attacker-controlled Origin. With #30741 (loopback-only) just merged, this is the last common-case DNS rebinding gap on the dashboard surface.
Changes
hermes_cli/web_server.py: new_ws_host_origin_is_allowed()+_ws_request_is_allowed()reusing the existing_is_accepted_host()helper. Applied to all 4 WS endpoints:/api/pty,/api/ws,/api/pub,/api/events. Host always checked; Origin checked only when present (so non-browser WS clients keep working).tests/hermes_cli/test_web_server_host_header.py: 4 new WebSocket cases — rebinding Host rejected, rebinding Origin rejected, loopback Host+Origin accepted, missing-Origin permissive.tests/hermes_cli/test_web_server.py: existing WS sidecar test updated to send loopback Host+Origin headers (otherwise the new guard rejects the bare TestClient handshake).Test plan
Co-authored-by: Hinotoi-agent paperlantern.agent@gmail.com
Closes #30221