trackslash
TRACK-10 P2

Fail closed on WebSocket origins in production

0
All issues

Description

Problem

WebSocket origin validation explicitly permits every origin when CORS_ALLOWED_ORIGINS is empty (internal/realtime/ws.go:16-28, :40-56). Server construction documents that the empty default leaves WebSockets open for development (internal/server/server.go:33-35), and both the bearer-authenticated API socket and cookie-authenticated UI socket receive this same list.

The production deployment guide requires TRACK_SLASH_PUBLIC_ORIGIN but does not require CORS_ALLOWED_ORIGINS (DEPLOYMENT.md:59-65). As a result, a normal production configuration can retain the fail-open WebSocket policy.

Impact

A malicious browser origin that can send the user's cookie—most notably an untrusted same-site sibling origin—can establish the UI WebSocket as the victim and subscribe to authorized project topics. Topic authorization limits the blast radius to the victim's access, but cross-site event observation and traffic analysis remain possible.

Acceptance criteria

  • Derive the browser WebSocket allow-list from the validated public origin independently of whether cross-origin API CORS is enabled.
  • Fail closed for non-empty browser Origin values in deployed mode; make permissive localhost development explicit.
  • Keep a documented path for non-browser bearer-token clients that omit Origin.
  • Ensure API and UI WebSocket endpoints use the intended, separately testable policy.
  • Add tests for default production config, allowed same-origin, rejected foreign/sibling origin, empty non-browser Origin, and localhost development.
  • Update deployment documentation so a secure production default does not depend on an optional CORS variable.

Sub-issues

0

Linked issues

0

GitHub

0

No branches or pull requests linked.

Comments

1