PD-32 — Revue Sécurité¶
Résumé¶
| Critère | Statut |
|---|---|
| Forbidden patterns | ❌ |
| Injection SQL | ✅ |
| Auth/Authz | ❌ |
| Fuite données | ✅ |
| Validation | ❌ |
Verdict : ⚠️ RÉSERVES
Audit des forbidden patterns¶
| Pattern interdit | Recherché | Trouvé |
|---|---|---|
| Accès direct au repository sans passer par UserProfileService (controller) | Repository usage dans controller | ✅ Absence |
| Exposition de routes avec paramètre userId | Route type /user/:id | ✅ Absence |
| Bypass des guards par configuration ou décorateurs | Guard auth/rate-limit sur endpoint | ❌ Risque (rate-limit non visible au controller) |
| Requêtes SQL brutes avec concaténation de paramètres | SQL dynamique concaténée | ✅ Absence |
| Exposition de champs sensibles dans les retours | passwordHash/srpSalt/validationToken dans DTO/réponse | ✅ Absence |
| Modification de champs protégés dans le service | Affectation email/plan/status/id | ✅ Absence |
| Propriété sans décorateur de validation explicite | Champs DTO non validés | ❌ Présence (sessionTimeout sans validation) |
| Désactivation de whitelist/forbidNonWhitelisted | ValidationPipe permissive | ❌ Non démontré dans ce code audité |
| Oubli de @ValidateNested() / @Type() sur preferences | Validation imbriquée | ✅ Absence |
Tentatives de bypass¶
| Attaque | Résultat | Commentaire |
|---|---|---|
Injection champ protégé { "email": "hack@evil.com" } | Bloqué (attendu 400) | Dépend de whitelist + forbidNonWhitelisted global, non visible ici. |
Injection SQL userId = "'; DROP TABLE--" | Échappé | SET LOCAL ... = $1 paramétré, pas de concat SQL. |
| Fuite champ sensible sur GET | Non observée | DTO réponse + excludeExtraneousValues limitent l’exposition. |
| Cross-access JWT user A / données user B | Mitigé mais dépend RLS | GET via RlsQueryService; PUT via SET LOCAL app.current_user_id; sécurité dépend activation RLS effective. |
| Bypass auth sans JWT | Bloqué (attendu 401) | @UseGuards(JwtAuthGuard) présent sur controller. |
Vulnérabilités identifiées¶
| ID | Description | Gravité | Fichier |
|---|---|---|---|
| S-01 | Protection rate limiting non explicitement appliquée sur le controller (@UseGuards(RateLimitGuard) absent dans le code audité) ; dépendance à une configuration globale non prouvée dans l’artefact. | MAJEUR | src/modules/user/controllers/user-profile.controller.ts |
| S-02 | Validation partielle de preferences.security.sessionTimeout (champ non typé/borne), ouvrant une surface d’entrée non strictement contrainte. | MAJEUR | src/modules/user/dto/user-preferences.dto.ts |
| S-03 | Cohérence contractuelle des codes d’erreur non alignée (ERR-32-01 observé vs schéma ERR-32-XXX métier attendu), réduisant l’auditabilité en cas d’attaque. | MINEUR | src/modules/user/services/user-profile.service.ts |
| S-04 | Mapping de nom de champ API avatar_url vs propriété avatarUrl dépend fortement de la transformation/sérialisation ; risque de contournement contractuel côté sortie/entrée si configuration incomplète. | MINEUR | src/modules/user/dto/update-user-profile.dto.ts, src/modules/user/dto/user-profile-response.dto.ts |
Recommandations¶
- Vérifier explicitement l’application effective du contrôle de débit sur ces endpoints dans la configuration runtime auditée.
- Renforcer la validation des champs numériques de préférences pour fermer les entrées faibles.
- Vérifier l’uniformité des codes d’erreur contractuels retournés par tous les chemins d’exception.
- Vérifier la cohérence de sérialisation/desérialisation des alias
avatar_url/avatarUrldans les réponses et payloads.