Description
Three related security gaps in the server:
-
packages/server/handler/websocket.go:17 — CheckOrigin returns
true for every request. Any browser on any origin can open a
WebSocket to any game.
-
packages/server/main.go:65 — Access-Control-Allow-Origin: *.
Combined with (1) and the unauthenticated REST API, this means a
third-party website can read state, join games, and submit moves on
the user's behalf.
-
packages/server/game/manager.go:71 — game IDs are 4 random bytes
(32 bits) hex-encoded. GET /api/games is unauthenticated and
returns IDs. An attacker can enumerate IDs by brute force and join
active games as a second client.
Proposed fix
- Replace
CheckOrigin with a whitelist driven by an env var
ALLOWED_ORIGINS (comma-separated). Default to http://localhost:3000
in dev. Reject if origin is missing and not same-host.
- Change CORS middleware to echo the request origin only if it is in
the whitelist (instead of *). Set
Access-Control-Allow-Credentials: true only when needed.
- Increase game ID entropy to 16 bytes (128 bits) hex-encoded. Use
crypto/rand (already used).
- Document the env vars in
README.md and .env.example.
Acceptance criteria
Files
packages/server/handler/websocket.go
packages/server/main.go
packages/server/game/manager.go
README.md
.env.example (new)
Description
Three related security gaps in the server:
packages/server/handler/websocket.go:17—CheckOriginreturnstruefor every request. Any browser on any origin can open aWebSocket to any game.
packages/server/main.go:65—Access-Control-Allow-Origin: *.Combined with (1) and the unauthenticated REST API, this means a
third-party website can read state, join games, and submit moves on
the user's behalf.
packages/server/game/manager.go:71— game IDs are 4 random bytes(32 bits) hex-encoded.
GET /api/gamesis unauthenticated andreturns IDs. An attacker can enumerate IDs by brute force and join
active games as a second client.
Proposed fix
CheckOriginwith a whitelist driven by an env varALLOWED_ORIGINS(comma-separated). Default tohttp://localhost:3000in dev. Reject if origin is missing and not same-host.
the whitelist (instead of
*). SetAccess-Control-Allow-Credentials: trueonly when needed.crypto/rand(already used).README.mdand.env.example.Acceptance criteria
http://evil.exampleis rejectedOrigin: http://localhost:3000is acceptedGET /api/games/{nonexistent}still 404s, but IDs are now 32 hex charsREADME.mdlists the new env varsFiles
packages/server/handler/websocket.gopackages/server/main.gopackages/server/game/manager.goREADME.md.env.example(new)