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

56 lines
2.5 KiB
Markdown

# 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