Files
Kordant/tasks/security-fixes/09-fix-websocket-origin-validation.md
2026-05-29 09:03:47 -04:00

2.5 KiB

09. Fix WebSocket no Origin header validation

meta: id: security-fixes-09 feature: security-fixes priority: P1 depends_on: [security-fixes-08] tags: [implementation, tests-required, medium-severity]

objective:

  • Prevent cross-origin WebSocket connections by validating the Origin header during the upgrade handshake

deliverables:

  • verifyClient callback on the WebSocket server that validates the Origin header
  • Configurable allowlist of trusted origins for WebSocket connections
  • Unit tests for Origin validation

steps:

  1. Examine web/src/server/websocket.ts:80-102 (WebSocketServer constructor and connection handler)
  2. Add a verifyClient callback to the WebSocketServer constructor:
    • Extract the Origin header from the upgrade request
    • Validate against a trusted origins allowlist (derived from APP_URL and localhost)
    • Reject connections with missing or untrusted Origin headers
  3. Define the trusted origins allowlist:
    • http://localhost:3000, http://localhost:3001 (development)
    • APP_URL (production, validated per task 05)
    • Optional: VALID_WEBSOCKET_ORIGINS env var for explicit configuration
  4. Ensure the Origin validation works with the post-connection auth flow from task 08
  5. Log rejected connections for monitoring

tests:

  • Unit: Connection from trusted origin (localhost:3000) is accepted
  • Unit: Connection from untrusted origin (https://evil.com) is rejected
  • Unit: Connection without an Origin header is rejected
  • Integration: WebSocket connection from a trusted page succeeds
  • Integration: WebSocket connection initiated from an untrusted page (via <script>) is rejected

acceptance_criteria:

  • WebSocket server validates the Origin header during the upgrade handshake
  • Connections from untrusted origins are rejected before authentication
  • Trusted origins include localhost (dev) and APP_URL (production)
  • Missing Origin headers are rejected
  • The Origin validation complements the JWT authentication from task 08

validation:

  • cd web && bun test — all tests pass
  • Connect from a trusted origin and verify the connection is accepted
  • Attempt to connect from an untrusted origin and verify it is rejected
  • Check server logs for rejected connection entries

notes:

  • Finding p8-009: The WebSocket server on port 3001 has no Origin validation
  • Depends on task 08 because the authentication flow needs to be established first
  • The verifyClient callback receives { origin, req, secure } — use origin for validation
  • Combined with task 08 (JWT auth), this closes the complete authentication bypass chain