Problem Statement
The StreamsGateway WebSocket namespace is configured with cors: { origin: "*" } at api/src/gateways/streams.gateway.ts:55. This allows any website on the internet to open a WebSocket connection to the gateway, perform JWT authentication, and subscribe to stream events. This enables Cross-Site WebSocket Hijacking (CSWSH) attacks where a malicious site opens a WebSocket to the victim's backend using the victim's credentials.
Evidence
// api/src/gateways/streams.gateway.ts:54-55
@WebSocketGateway({
namespace: "/streams",
cors: { origin: "*" },
})
The REST API correctly uses origin: process.env.CORS_ORIGIN || "http://localhost:3000" in api/src/main.ts:34. The WebSocket gateway should follow the same pattern.
Impact
A malicious website can open a WebSocket connection to wss://api.xstreamroll.io/streams, authenticate with the victim's JWT (obtained via XSS or cookie theft), and subscribe to all stream events. The attacker can also emit messages to the server (e.g., subscribe/unsubscribe to arbitrary streams) and potentially flood the victim's socket with events.
Proposed Solution
Replace cors: { origin: "*" } with cors: { origin: process.env.CORS_ORIGIN || "http://localhost:3000" }. For WebSocket connections, also configure credentials: true to match the REST API CORS settings if cookie-based auth is used on the WebSocket handshake.
Technical Requirements
- Must use the same CORS_ORIGIN env var as the REST API
- Must support multiple origins in production if needed (array of allowed origins)
- Must not break local development (localhost:3000)
Acceptance Criteria
File Map
api/src/gateways/streams.gateway.ts:55 — change CORS origin
Dependencies
- Related: REPO-001 (JWT auth must work on WebSocket too)
Testing Strategy
- Manual: Verify WebSocket connection rejected from different origin
- Manual: Verify WebSocket connection accepted from same origin
- Consider adding a WebSocket integration test
Security Considerations
This is a defense-in-depth measure. Even with proper JWT auth (REPO-001), a wildcard CORS policy allows any origin to present a valid JWT and interact with the WebSocket gateway. The origin check prevents the browser-based CSWSH attack vector entirely.
Definition of Done
Labels: security, quick win
Priority: High
Difficulty: Beginner
Estimated Effort: 0.5h
Milestone: v1.0-alpha
Labels: security,quick win
Priority: High | Difficulty: Beginner | Estimated Effort: 0.5h
Backlog ID: REPO-006
Problem Statement
The StreamsGateway WebSocket namespace is configured with
cors: { origin: "*" }atapi/src/gateways/streams.gateway.ts:55. This allows any website on the internet to open a WebSocket connection to the gateway, perform JWT authentication, and subscribe to stream events. This enables Cross-Site WebSocket Hijacking (CSWSH) attacks where a malicious site opens a WebSocket to the victim's backend using the victim's credentials.Evidence
The REST API correctly uses
origin: process.env.CORS_ORIGIN || "http://localhost:3000"inapi/src/main.ts:34. The WebSocket gateway should follow the same pattern.Impact
A malicious website can open a WebSocket connection to
wss://api.xstreamroll.io/streams, authenticate with the victim's JWT (obtained via XSS or cookie theft), and subscribe to all stream events. The attacker can also emit messages to the server (e.g., subscribe/unsubscribe to arbitrary streams) and potentially flood the victim's socket with events.Proposed Solution
Replace
cors: { origin: "*" }withcors: { origin: process.env.CORS_ORIGIN || "http://localhost:3000" }. For WebSocket connections, also configurecredentials: trueto match the REST API CORS settings if cookie-based auth is used on the WebSocket handshake.Technical Requirements
Acceptance Criteria
File Map
api/src/gateways/streams.gateway.ts:55— change CORS originDependencies
Testing Strategy
Security Considerations
This is a defense-in-depth measure. Even with proper JWT auth (REPO-001), a wildcard CORS policy allows any origin to present a valid JWT and interact with the WebSocket gateway. The origin check prevents the browser-based CSWSH attack vector entirely.
Definition of Done
Labels: security, quick win
Priority: High
Difficulty: Beginner
Estimated Effort: 0.5h
Milestone: v1.0-alpha
Labels: security,quick win
Priority: High | Difficulty: Beginner | Estimated Effort: 0.5h
Backlog ID: REPO-006