56 lines
2.5 KiB
Markdown
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
|