Skip to content

[Security] Lock down CORS, WebSocket origin check, and lengthen game IDs #7

Description

@dev-rkb

Description

Three related security gaps in the server:

  1. packages/server/handler/websocket.go:17CheckOrigin returns
    true for every request.
    Any browser on any origin can open a
    WebSocket to any game.

  2. packages/server/main.go:65Access-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.

  3. 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

  • A WebSocket connection from http://evil.example is rejected
  • A request with Origin: http://localhost:3000 is accepted
  • GET /api/games/{nonexistent} still 404s, but IDs are now 32 hex chars
  • README.md lists the new env vars

Files

  • packages/server/handler/websocket.go
  • packages/server/main.go
  • packages/server/game/manager.go
  • README.md
  • .env.example (new)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions