feat(server): harden configuration for public exposure (#52) #68

Merged
Reliodas merged 2 commits from feat/52-vps-hardening into develop 2026-06-25 20:55:30 +00:00
Owner

Closes #52

Passe de durcissement sécurité pour une exposition publique derrière reverse proxy.

Changements serveur

  • config.ts (testé) : ALLOWED_ORIGINS (liste blanche CORS explicite ; prod fermée par défaut), TRUST_PROXY (bool / nb de sauts / sous-réseau), SOCKET_MAX_BUFFER_BYTES (défaut 8 Kio).
  • security-headers.ts : CSP adaptée au SPA (default-src 'self', script-src 'self', style-src 'self' 'unsafe-inline', connect-src 'self', frame-ancestors 'none'…), X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy, COOP, Permissions-Policy. HSTS laissé au proxy.
  • app.ts : trustProxy depuis l'env, headers sur chaque réponse, maxHttpBufferSize (cap de trame), CORS depuis la config.
  • rate-limit.ts : journalisation des rejets de fréquence, une fois par fenêtre/socket, sans payload ni token (logger injectable, silencieux hors production).
  • smoke.ts : vérifie désormais les en-têtes de sécurité.

Docs

docs/Securite.md (nouveau) : variables d'env, stratégie trust proxy, en-têtes, limites Socket.IO (validation, taille de trame, fréquence 30/s, cap de salles), revue du stockage localStorage du token de reconnexion et de sa TTL (RECONNECT_GRACE_SECONDS 30 s), journalisation des rejets, et checklist de déploiement. Lié depuis le README.

Conformité aux critères

origine autorisée via env ✓ · en-têtes HTTP adaptés au client statique ✓ · stratégie trust proxy documentée ✓ · limites taille/fréquence vérifiées (cap de trame + rate-limit) ✓ · revue token/TTL ✓ · logs de rejet sans secret ✓ · tests + checklist ✓

Vérification

  • typecheck OK ; node:test 232 pass (1 skipped), Jest 13/13, Vitest 83/83 ; coverage exit 0
  • e2e Playwright 3/3 : la CSP ne casse ni le SPA ni le WebSocket (connect-src 'self' validé en navigateur)
  • npm run smoke vert (inclut la vérification des en-têtes), build OK, check:assets OK, validate:questions OK (360)
Closes #52 Passe de durcissement sécurité pour une exposition publique derrière reverse proxy. ## Changements serveur - **`config.ts`** (testé) : `ALLOWED_ORIGINS` (liste blanche CORS explicite ; prod fermée par défaut), `TRUST_PROXY` (bool / nb de sauts / sous-réseau), `SOCKET_MAX_BUFFER_BYTES` (défaut 8 Kio). - **`security-headers.ts`** : CSP adaptée au SPA (`default-src 'self'`, `script-src 'self'`, `style-src 'self' 'unsafe-inline'`, `connect-src 'self'`, `frame-ancestors 'none'`…), `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Referrer-Policy`, `COOP`, `Permissions-Policy`. HSTS laissé au proxy. - **`app.ts`** : `trustProxy` depuis l'env, headers sur chaque réponse, `maxHttpBufferSize` (cap de trame), CORS depuis la config. - **`rate-limit.ts`** : journalisation des rejets de fréquence, **une fois par fenêtre/socket, sans payload ni token** (logger injectable, silencieux hors production). - **`smoke.ts`** : vérifie désormais les en-têtes de sécurité. ## Docs `docs/Securite.md` (nouveau) : variables d'env, stratégie trust proxy, en-têtes, limites Socket.IO (validation, taille de trame, fréquence 30/s, cap de salles), revue du stockage `localStorage` du token de reconnexion et de sa TTL (`RECONNECT_GRACE_SECONDS` 30 s), journalisation des rejets, et **checklist de déploiement**. Lié depuis le README. ## Conformité aux critères origine autorisée via env ✓ · en-têtes HTTP adaptés au client statique ✓ · stratégie trust proxy documentée ✓ · limites taille/fréquence vérifiées (cap de trame + rate-limit) ✓ · revue token/TTL ✓ · logs de rejet sans secret ✓ · tests + checklist ✓ ## Vérification - typecheck OK ; `node:test` 232 pass (1 skipped), Jest 13/13, Vitest 83/83 ; coverage exit 0 - **e2e Playwright 3/3** : la CSP ne casse ni le SPA ni le WebSocket (`connect-src 'self'` validé en navigateur) - `npm run smoke` vert (inclut la vérification des en-têtes), build OK, check:assets OK, validate:questions OK (360)
Add a tested config module parsing ALLOWED_ORIGINS (explicit CORS allowlist),
TRUST_PROXY and SOCKET_MAX_BUFFER_BYTES. Set HTTP security headers (CSP suited to
the SPA, nosniff, frame DENY, referrer, COOP, permissions) on every response, cap
the Socket.IO frame size, and honour reverse-proxy headers only when enabled.
Log rate-limit rejections once per window without payloads or tokens. The smoke
test now asserts the security headers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(security): add the public-exposure hardening guide (#52)
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
84aff488f5
Document the environment variables, trust-proxy strategy, security headers,
Socket.IO limits, reconnect-token storage and TTL, rejection logging and a
deployment checklist in docs/Securite.md, linked from the README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reliodas merged commit a917e048bc into develop 2026-06-25 20:55:30 +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#68
No description provided.