Aller au contenu

PD-85 — 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é
createVerify(ALG).update(hash) Oui ✅ Absent
Math.random() Oui ✅ Absent
S3 GetObject / decrypt Oui ✅ Absent
fire-and-forget audit Oui ❌ Trouvé dans catch path
Secret exposure en DTOs Oui ✅ Absent

Tentatives de bypass

Attaque Résultat Commentaire
SQLi via proofId Bloqué DTO UUID v4 + requête paramétrée
Cross-access JWT A / proofs B Bloqué Ownership check présent
Bypass auth sans JWT Bloqué OidcJwtAuthGuard
Bypass premium FREE Bloqué PremiumGuard → 403
501 proofIds Bloqué @ArrayMaxSize(500)
Duplicate IDs Bloqué @ArrayUnique()
Secret pattern "password" Bloqué SecretExposureValidator

Vulnérabilités identifiées

ID Description Gravité Fichier
S-01 Audit non fail-closed dans catch path : .catch(...) absorbe l'échec d'audit puis continue avec ExportException. Opération sans trace WORM possible CRITIQUE export.service.ts:181
S-02 Énumération d'existence de ressources : messages d'erreur distincts ("Proof not found" vs "Proof not accessible") avec proofId — permet profiling des IDs valides MAJEUR export.service.ts:199,213
S-03 TTL URL signée non borné en code : signedUrlTtlMin utilisé sans clamp <= 30. Mauvaise config = URLs trop longues (INV-85-04) MAJEUR export.service.ts:302
S-04 Secret exposure validator contournable : détection par substring simple (homoglyphes, encodage base64, synonymes non listés). Risque faux négatifs RÉSERVE secret-exposure.validator.ts
S-05 DoS applicatif : checkOwnership fait 2 accès DB par proofId (jusqu'à 500). Sous rafale, amplification CPU/DB significative MOYEN export.service.ts:192-218
S-06 UUID case sensitivity : @ArrayUnique compare les strings telles quelles. Deux formes (upper/lower) du même UUID passent comme uniques MOYEN complaint-file-request.dto.ts
S-07 Exposition d'infos internes : logger.error(message, stack) + metadata audit avec error.message peut divulguer détails internes MINEUR export.service.ts:170-185
S-08 Metadata audit : ...metadata mergé en dernier peut écraser champs réservés (result, exportId) FAIBLE export.service.ts:364

Barrières primaires identifiées

Barrière Composant Protection
Auth JWT OidcJwtAuthGuard Authentification Keycloak
Plan check PremiumGuard Filtrage FREE
RLS ownership checkOwnership + SQL paramétré Isolation données
S3 presign getSignedUrl sans GetObject Zero-Knowledge
Encryption at rest AES-256-GCM / HSM Protection données au repos

Recommandations prioritaires

  1. Rendre l'audit strictement fail-closed dans le catch (si audit KO → 503, jamais absorber)
  2. Uniformiser les messages d'erreur 404 (même message pour found vs accessible)
  3. Borner TTL en code : Math.min(config, 1800) + validation Joi fail-fast
  4. Remplacer ownership N+1 par requête set-based WHERE proof_id IN (...) avec JOIN
  5. Normaliser UUID lowercase avant @ArrayUnique