feat(socket): validate and rate-limit every incoming event (#3) #27

Merged
Reliodas merged 1 commit from sec/3-validate-socket-events into develop 2026-06-22 23:52:37 +00:00
Owner

Implements ticket #3 — validate and limit all incoming Socket.IO events.

Problem

Payloads were destructured with ad-hoc checks: a missing payload could throw, several strings had no server bound, and there was no rate limiting or room-creation quota.

Changes

  • Per-event schemas (server/src/socket/validation.ts): every incoming event is validated and normalized. Missing, mistyped or oversized payloads are rejected; the room code is uppercased and must be exactly four letters; string bounds live in server/src/socket/limits.ts. Room events answer with an explicit room:error; invalid game events are dropped silently (no feedback to hostile clients).
  • Rate limiting (server/src/socket/rate-limit.ts): per-socket fixed-window cap across all events, cleared on disconnect.
  • Room quota: global MAX_ACTIVE_ROOMS cap (via room.store.roomCount) refuses creation beyond the limit.

Verification (local, all green)

  • Server node:test 111 pass / 1 skip (validators, limiter, roomCount, hostile-input integration)
  • Server Jest 9 pass; c8 coverage 84.4 / 83.7 / 90 / 84.4 — above floors and improved (validation.ts & rate-limit.ts at 100%)
  • Client Vitest 42 pass + production build OK; typechecks clean across packages (no client/shared changes)

Docs updated: docs/Implémentation.md (validation & limits section, tests, limits).

Refs #3

Implements ticket #3 — validate and limit all incoming Socket.IO events. ## Problem Payloads were destructured with ad-hoc checks: a missing payload could throw, several strings had no server bound, and there was no rate limiting or room-creation quota. ## Changes - **Per-event schemas** (`server/src/socket/validation.ts`): every incoming event is validated and normalized. Missing, mistyped or oversized payloads are rejected; the room code is uppercased and must be exactly four letters; string bounds live in `server/src/socket/limits.ts`. Room events answer with an explicit `room:error`; invalid game events are dropped silently (no feedback to hostile clients). - **Rate limiting** (`server/src/socket/rate-limit.ts`): per-socket fixed-window cap across all events, cleared on disconnect. - **Room quota**: global `MAX_ACTIVE_ROOMS` cap (via `room.store.roomCount`) refuses creation beyond the limit. ## Verification (local, all green) - Server `node:test` 111 pass / 1 skip (validators, limiter, roomCount, hostile-input integration) - Server Jest 9 pass; c8 coverage 84.4 / 83.7 / 90 / 84.4 — above floors and improved (`validation.ts` & `rate-limit.ts` at 100%) - Client Vitest 42 pass + production build OK; typechecks clean across packages (no client/shared changes) Docs updated: `docs/Implémentation.md` (validation & limits section, tests, limits). Refs #3
feat(socket): validate and rate-limit every incoming event
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
a24c063f77
Incoming payloads were destructured with ad-hoc checks: a missing payload
could throw, several strings had no server-side bound, and there was no
rate limiting or room-creation quota.

- validation: server/src/socket/validation.ts defines a schema per event.
  Untrusted payloads that are missing, mistyped or oversized are rejected and
  normalized (room code uppercased to exactly four letters); string bounds live
  in server/src/socket/limits.ts. Room events answer with an explicit
  room:error; invalid game events are dropped silently.
- rate limiting: server/src/socket/rate-limit.ts enforces a per-socket
  fixed-window cap across all events, cleared on disconnect.
- quota: a global MAX_ACTIVE_ROOMS cap (via room.store.roomCount) refuses room
  creation beyond the limit.

Covered by unit tests for the validators and the limiter, a roomCount store
test, and integration tests for hostile inputs (malformed create, oversized
name, bad code, unknown action) confirming no crash and no state change. Docs
updated.

Refs #3

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reliodas merged commit 4af0009f37 into develop 2026-06-22 23:52:37 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: jeux/le-grand-concours#27
No description provided.