Baseline sécurité¶
Référentiel vivant des contrôles de sécurité que WonderWork s'engage à tenir, et de leur statut. Il matérialise l'ADR 0002.
| Niveau cible | OWASP ASVS L2 |
| Version ancrée | ASVS 5.0.0 (mai 2025, 17 chapitres) |
| Dernière revue | 2026-10-13 |
| Prochaine revue | Audit complet périodique (voir Maintenance) |
L2 est justifié par des données RH B2B et l'exposition RGPD : le standard des applications métier manipulant des données sensibles. Les niveaux sont cumulatifs (L2 inclut L1).
Modèle de menace¶
Le catalogue d'attaques dont on se protège est cadré par OWASP Top 10 (risques applicatifs) et OWASP API Security Top 10 (risques spécifiques à l'API). ASVS est la grille de vérification ; les Top 10 sont le modèle de menace.
Comment lire ce doc¶
Statuts (vocabulaire contrôlé) :
| Statut | Sens |
|---|---|
Tenu |
Implémenté et vérifié (test ou PR à l'appui) |
Partiel |
Partiellement couvert, écart nommé |
À faire |
Écart connu et tracé (PR, stub, US) |
Non applicable |
Hors périmètre, justifié |
Non évalué |
Pas encore audité (honnêteté assumée, pas de faux vert) |
Granularité des références. Ce doc n'est pas un audit ligne à ligne des ~200 exigences L2 :
c'est un suivi des contrôles qu'on s'engage à tenir. Les références ASVS sont au niveau chapitre
(ex. V8). Le mapping fin par exigence (ex. v5.0.0-8.2.1) est pinné lors de l'audit complet.
Périmètre. Ce doc couvre la couche applicative (api + fronts Next). Les contrôles délégués à l'edge/infra (TLS, headers nginx, durcissement réseau) sont tracés en Hors périmètre applicatif et renvoient aux tâches DevOps.
Chapitres ASVS¶
V1 Encoding & Sanitization, Partiel¶
Protections au niveau framework : requêtes paramétrées Doctrine (pas de SQL brut), échappement de sortie React par défaut, sérialisation via API Platform. Non audité exigence par exigence.
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Requêtes paramétrées (pas d'injection SQL) | Tenu | Doctrine ORM | dev |
| Échappement de sortie côté front | Tenu | React (défaut) | dev |
V2 Validation & Business Logic, Partiel¶
Validation d'entrée systématique via DTO + contraintes Symfony Validator (jamais sur les entités). Règles métier protégées par des gardes atomiques (ex. transitions d'étape de candidature).
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Validation d'entrée sur DTO (pas sur entités) | Tenu | convention api | dev |
| Gardes atomiques sur transitions d'état | Tenu | ApplicationEvent | dev |
V3 Web Frontend Security, Partiel¶
Headers de sécurité applicatifs posés sur les 3 apps Next (CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy). La moitié edge (nginx) reste à poser.
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Headers de sécurité couche app | Tenu | #187 | dev |
| CSP différenciée par app (LiveKit candidate/recruiter) | Tenu | #187 | dev |
| Headers de sécurité edge nginx | À faire | stub DevOps | DevOps |
| Durcissement CSP nonce-based | À faire | follow-up #187 | dev |
V4 API & Web Service, Partiel¶
API Platform, JSON-LD partout, DTO en entrée/sortie (jamais d'entités exposées). Doc API gatée hors dev. Rate limiting en place sur les surfaces sensibles (score on-demand, demande de démo).
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| DTO en entrée/sortie, pas d'entité exposée | Tenu | convention api | dev |
Doc API (/v1/docs, Scalar) non publique hors dev |
Tenu | #178 | dev |
| Rate limiting sur surfaces sensibles | Partiel | on-demand 50/h, demo | dev |
V5 File Handling, Partiel¶
Uploads photo/media via Flysystem, détection de type MIME. Photos candidat et company stockées dans leur
propre espace (photos/{userId}/, companies/{companyId}/), fuites de fichiers au remplacement/suppression
fermées. Écart restant : le GC des uploads abandonnés (jamais rattachés) reste différé (Low, pas de driver conformité).
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Validation de type sur upload | Partiel | FileinfoMimeTypeGuesser | dev |
| Photos stockées dans l'espace de leur propriétaire | Tenu | #181, #191 | dev |
| Pas de fuite de fichier au remplacement/suppression | Tenu | #191 | dev |
| GC des uploads abandonnés | À faire | stub différé | dev |
V6 Authentication, Partiel¶
CTI users → candidates/recruiters. Politique de mot de passe NIST 2024 (min 12, pas de complexité imposée).
Réponses anti-énumération sur les flux sensibles (login, reset). Tokens d'auth hashés at rest.
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Politique mot de passe NIST (min 12) | Tenu | US-020 | dev |
| Anti-énumération login / reset | Tenu | US-020 | dev |
| Tokens d'auth hashés at rest | Tenu | US-020 | dev |
| MFA | Non évalué | - | dev |
V7 Session Management, Tenu¶
Access JWT 15 min + refresh token opaque en base. Cookie 30 j candidat, session recruteur. Détection de vol par rotation du refresh token.
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Access token court + refresh opaque BDD | Tenu | archi auth | dev |
| Theft detection par rotation | Tenu | archi auth | dev |
| Cookies httpOnly / Secure / SameSite | Partiel | à revérifier | dev |
V8 Authorization, Partiel¶
Isolation multi-tenant centralisée dans un TenantGuard (interface CompanyOwned), couverte par un test
d'architecture. Role security déclarée sur les opérations passport. Écart : tous les endpoints ne passent pas
encore par des Voters Symfony (levier WS3 restant).
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Isolation multi-tenant centralisée | Tenu | #185 | dev |
| Test d'archi multi-tenant | Tenu | #185 | dev |
| Role security sur opérations sensibles | Partiel | #180 | dev |
| Généralisation Voters Symfony | À faire | WS3 back | dev |
V9 Self-contained Tokens, Partiel¶
JWT HS256 pour les grants LiveKit (validés côté serveur). Tokens signés stateless pour les liens email (désinscription bubbles).
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Grant LiveKit signé + validé serveur | Tenu | US-034 | dev |
| Tokens email signés stateless | Tenu | bubbles alerts | dev |
V10 OAuth & OIDC, Non applicable¶
Pas de login tiers ni social, pas de fournisseur d'identité OAuth/OIDC. L'authentification repose sur les JWT
maison (couverts par V9). À rebasculer en À faire si un SSO entreprise recruteur est introduit.
V11 Cryptography, Partiel¶
Tokens sensibles hashés at rest, mots de passe hashés par le composant Symfony Security. Gestion des secrets via variables d'environnement (pas de secret prod versionné).
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Tokens / mots de passe hashés at rest | Tenu | US-020 | dev |
| Pas de secret prod versionné | Tenu | audit 2026-10 | dev |
| Rotation / gestion de clés | Non évalué | - | DevOps |
V12 Secure Communication, À faire¶
TLS terminé à l'edge nginx (couche infra). Le header HSTS est posé côté app ; sa pleine application dépend de la terminaison TLS edge.
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| HSTS (header couche app) | Tenu | #187 | dev |
| Terminaison TLS edge | À faire | stub DevOps | DevOps |
V13 Configuration, Partiel¶
Doc API gatée hors dev (secure-by-default). Config prod Ansible à finaliser (bloquant pré-prod, côté DevOps).
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Doc API non publique hors dev | Tenu | #178 | dev |
| Durcissement prod réel du stack docker | Tenu | audit 2026-10 | dev |
| Config Ansible prod finalisée | À faire | stub DevOps | DevOps |
V14 Data Protection, Partiel¶
RGPD : minimisation, pas d'attributs protégés dans l'algo de matching, rétention CNIL, soft delete + purge 30 j. Infrastructure 100 % française (pas de service US en prod).
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Minimisation + pas d'attribut protégé en algo | Tenu | convention projet | dev |
| Soft delete + purge 30 j | Tenu | archi suppression | dev |
| Rétention CNIL (candidatures, comptes, logs) | Partiel | à instrumenter | dev |
| Hébergement français | Tenu | ADR infra | DevOps |
V15 Secure Coding & Architecture, Partiel¶
PHPStan niveau 8, DTO systématiques, tests d'architecture (isolation multi-tenant). Audit de dépendances tenu à jour. Détection de code mort outillée à mettre en place.
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Analyse statique stricte (PHPStan L8) | Tenu | CI | dev |
| Tests d'architecture | Partiel | #185 | dev |
| Audit de dépendances (composer audit 13→0) | Tenu | #186 | dev |
| Détection de code mort outillée | À faire | brainstorming | dev |
V16 Security Logging & Error Handling, Partiel¶
Pas de donnée personnelle en logs (IDs et événements techniques uniquement). Réponses 404 anti-énumération, messages d'erreur génériques. Rétention des logs à aligner sur la CNIL.
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Pas de PII en logs | Tenu | convention RGPD | dev |
| 404 anti-énumération / erreurs génériques | Tenu | #185, US-020 | dev |
| Rétention logs CNIL (6 mois) | À faire | à instrumenter | DevOps |
V17 WebRTC, Partiel¶
Visio LiveKit self-host (RGPD, pas de SaaS US). Webhook d'attendance fail-closed. Grant HS256 validé côté serveur. Permissions-Policy caméra/micro restreinte aux apps concernées.
| Contrôle | Statut | Référence | Owner |
|---|---|---|---|
| Media server self-host (souveraineté) | Tenu | US-034 | DevOps |
| Webhook fail-closed | Tenu | US attendance | dev |
| Permissions-Policy caméra/micro ciblée | Tenu | #187 | dev |
Hors périmètre applicatif¶
Contrôles délégués à l'edge/infra, tracés côté DevOps (stubs Notion, assignés Brian) :
- Headers de sécurité à l'edge nginx (V3, V12).
- Terminaison et durcissement TLS (V12).
- Finalisation de la config Ansible prod (V13).
- Restriction de l'exposition publique de SonarQube et du site docs.
- Durcissement du scanning de sécurité et du réseau du stack dev.
Maintenance¶
Doc vivant, deux rythmes :
- Au fil de l'eau. Une PR qui change le statut d'un contrôle suivi met à jour la ligne concernée.
C'est un réflexe à la charge de l'auteur, pas un gate : pas de blocage de merge sur la conformité ASVS
en phase pré-lancement. Le skill
security-reviewapplique cette lentille sur le diff d'une branche et porte ce rappel en étape finale (boucle baseline). - Périodique. Un audit complet du codebase contre ASVS revalide l'ensemble du doc, pinne les IDs d'exigence fins, et met à jour la date de dernière revue. C'est à ce moment qu'on arbitre une montée de couverture (vers L3 sur certains chapitres si le risque le justifie).