veza/PENTEST_REPORT_VEZA_v0.12.6.md
senke a5069c9311 feat(v0.12.6): pentest OWASP Top 10 + ASVS Level 2 — 3 reports
Internal security audit replacing external pentester.
Methodology: OWASP Top 10 (2021), API Security Top 10 (2023), ASVS v4.0 Level 2.

Results: 0 CRITICAL, 3 HIGH, 8 MEDIUM, 6 LOW, 5 INFO.
ASVS Level 2: 82% PASS, 2 FAIL (to fix), 15% PARTIAL.

Deliverables:
- PENTEST_REPORT_VEZA_v0.12.6.md (main report)
- REMEDIATION_MATRIX_v0.12.6.md (prioritized actions)
- ASVS_CHECKLIST_v0.12.6.md (item-by-item ASVS Level 2)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:31:27 +01:00

28 KiB

RAPPORT DE PENTEST — VEZA v0.12.6

Champ Valeur
Date 2026-03-11
Auditeur Claude Opus 4.6 — Audit de sécurité interne (remplace prestataire externe)
Version analysée v0.12.6 (branche feat/v0.12.6-pentest-audit)
Périmètre Backend Go, Stream Server Rust, Frontend React, Infrastructure Docker, CI/CD
Méthodologie OWASP Top 10 (2021), OWASP API Security Top 10 (2023), ASVS v4.0 Level 2
Classification Confidentiel — Usage interne

EXECUTIVE SUMMARY

Verdict global

Le codebase VEZA est globalement bien sécurisé avec une architecture de sécurité mature (middleware chain, RBAC, token versioning, CSRF, rate limiting multi-couche). Les vulnérabilités critiques identifiées dans l'audit précédent (mars 2026) ont été corrigées (VEZA-SEC-001 JWT secret par défaut, VEZA-SEC-002 issuer/audience mismatch).

Recommandation : GO CONDITIONNEL

L'audit identifie 0 finding CRITIQUE, 3 findings HAUTS, 8 findings MOYENS, 6 findings BAS, et 5 findings INFO. Les findings HAUTS doivent être corrigés avant le GO v1.0.0.

Résumé des findings

Sévérité Nombre Détail
CRITIQUE 0
HAUTE 3 Race condition marketplace, production HS256, user repository context bypass
MOYENNE 8 Recovery codes math/rand, metrics IP spoofing, ClamAV latest, pagination sans limit max, WebSocket rate limit gaps, CORS Swagger CSP, CI actions non-pinnées, RabbitMQ mgmt exposé
BASSE 6 Password policy mismatch FE/BE, Hyperswitch version, dotenv crate, Elasticsearch sans auth, context.Background dans workers, exported debug endpoints
INFO 5 Bonnes pratiques confirmées, recommandations d'amélioration

FINDINGS DÉTAILLÉS


[HIGH-001] : Race condition TOCTOU sur le compteur de téléchargements marketplace

Sévérité : HAUTE CVSS v3.1 : 7.5 (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N) CWE : CWE-367 — Time-of-check Time-of-use (TOCTOU) Race Condition OWASP : A04:2021 — Insecure Design OWASP API : API6:2023 — Unrestricted Access to Sensitive Business Flows Fichier(s) : veza-backend-api/internal/core/marketplace/service.go:794-817 Composant : Marketplace — Downloads

Description La fonction GetDownloadURL vérifie d'abord qu'une licence existe avec downloads_left > 0 (ligne 794), puis décrémente downloads_left séparément (ligne 817). Ces deux opérations ne sont pas atomiques et ne sont pas dans une transaction avec verrouillage.

Preuve de concept

# Deux requêtes simultanées avec downloads_left = 1
# T1: SELECT ... WHERE downloads_left > 0 → trouvé (downloads_left = 1)
# T2: SELECT ... WHERE downloads_left > 0 → trouvé (downloads_left = 1)
# T1: UPDATE downloads_left = downloads_left - 1 → downloads_left = 0
# T2: UPDATE downloads_left = downloads_left - 1 → downloads_left = -1
# Résultat: 2 téléchargements au lieu de 1

Impact Un acheteur peut contourner la limite de téléchargements d'une licence en envoyant plusieurs requêtes simultanées. Impact financier direct pour les créateurs vendant des licences exclusives à téléchargements limités.

Remédiation

// Utiliser une transaction avec SELECT FOR UPDATE
tx := s.db.Begin()
err := tx.Set("gorm:query_option", "FOR UPDATE").
    Where("buyer_id = ? AND product_id = ? AND downloads_left > 0 AND revoked_at IS NULL", buyerID, productID).
    First(&license).Error
if err != nil {
    tx.Rollback()
    return "", ErrNoLicense
}
// ... generate URL ...
tx.Model(&license).Update("downloads_left", gorm.Expr("downloads_left - 1"))
tx.Commit()

Alternativement : UPDATE ... SET downloads_left = downloads_left - 1 WHERE downloads_left > 0 RETURNING *

Priorité de correction : Sprint suivant


[HIGH-002] : Production déployée en HS256 au lieu de RS256

Sévérité : HAUTE CVSS v3.1 : 7.4 (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N) CWE : CWE-327 — Use of a Broken or Risky Cryptographic Algorithm OWASP : A02:2021 — Cryptographic Failures Fichier(s) : docker-compose.prod.yml:158, veza-backend-api/internal/services/jwt_service.go:32-79 Composant : Authentication — JWT

Description Le docker-compose.prod.yml configure JWT_SECRET (ligne 158) mais pas JWT_PRIVATE_KEY_PATH ni JWT_PUBLIC_KEY_PATH. Le code Go préfère RS256 si les clés sont fournies, sinon fallback HS256. En production, c'est HS256 qui est utilisé.

HS256 utilise un secret partagé symétrique — si le secret est compromis (leak env var, backup, log), un attaquant peut forger des tokens valides. RS256 nécessite la clé privée pour signer mais la clé publique suffit pour vérifier — meilleure séparation des responsabilités.

Impact Compromission du JWT_SECRET = compromission de tous les comptes utilisateurs. Avec RS256, seul le serveur ayant la clé privée peut signer des tokens.

Remédiation

  1. Générer une paire RSA 2048-bit pour la production
  2. Ajouter dans docker-compose.prod.yml :
    - JWT_PRIVATE_KEY_PATH=/secrets/jwt_private.pem
    - JWT_PUBLIC_KEY_PATH=/secrets/jwt_public.pem
    
  3. Monter les clés via Docker secrets ou volume sécurisé
  4. Supprimer JWT_SECRET de la config production
  5. Invalider tous les tokens existants (incrémenter token_version globalement)

Priorité de correction : Immédiate (avant v1.0.0)


[HIGH-003] : User repository bypass du context de requête

Sévérité : HAUTE CVSS v3.1 : 5.3 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L) CWE : CWE-400 — Uncontrolled Resource Consumption OWASP : A04:2021 — Insecure Design Fichier(s) : veza-backend-api/internal/repositories/user_repository.go:125-150 Composant : Data Layer — User Repository

Description Six méthodes du UserRepository (GetByID, GetByEmail, GetByUsername, Create, Update, Delete) utilisent context.Background() au lieu de propager le context de la requête HTTP. Cela signifie que :

  1. Les timeouts de requête ne s'appliquent pas aux opérations DB sous-jacentes
  2. L'annulation de la requête (client disconnect) ne cancelle pas la query DB
  3. Un attaquant peut déclencher des requêtes DB longues qui ne seront pas annulées

Impact Sous charge, des requêtes lentes peuvent s'accumuler car elles ne sont pas annulées quand le client se déconnecte. Cela peut mener à une saturation du pool de connexions DB (DoS).

Remédiation

// Avant (ligne 125)
func (r *UserRepository) GetByID(userID uuid.UUID) (*models.User, error) {
    return r.GetUserByID(context.Background(), userID)
}

// Après
func (r *UserRepository) GetByID(ctx context.Context, userID uuid.UUID) (*models.User, error) {
    return r.GetUserByID(ctx, userID)
}

Propager le context dans toute la chaîne d'appel (handler → service → repository).

Priorité de correction : Sprint suivant


[MEDIUM-001] : Codes de récupération 2FA générés avec math/rand

Sévérité : MOYENNE CVSS v3.1 : 5.9 (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N) CWE : CWE-338 — Use of Cryptographically Weak PRNG OWASP : A02:2021 — Cryptographic Failures ASVS : V2.6.1 Fichier(s) : veza-backend-api/internal/services/two_factor_service.go:200 Composant : Authentication — 2FA

Description Les codes de récupération 2FA sont générés avec mathrand.Intn() (math/rand) au lieu de crypto/rand. math/rand utilise un PRNG prédictible — si un attaquant connaît le seed ou peut observer suffisamment de sorties, il peut prédire les codes de récupération futurs.

Preuve de concept

// Ligne 200 - Utilisation de math/rand
code[j] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[mathrand.Intn(36)]

Depuis Go 1.20, math/rand auto-seed est non déterministe, réduisant le risque. Cependant, les standards cryptographiques exigent crypto/rand pour tout matériel lié à l'authentification.

Impact Prédiction théorique des codes de récupération 2FA, permettant le contournement de l'authentification à deux facteurs.

Remédiation

import "crypto/rand"
import "math/big"

for j := 0; j < 8; j++ {
    n, _ := rand.Int(rand.Reader, big.NewInt(36))
    code[j] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[n.Int64()]
}

Priorité de correction : Sprint suivant


[MEDIUM-002] : Bypass du whitelist IP des métriques via X-Forwarded-For

Sévérité : MOYENNE CVSS v3.1 : 5.3 (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) CWE : CWE-290 — Authentication Bypass by Spoofing OWASP : A05:2021 — Security Misconfiguration Fichier(s) : veza-backend-api/internal/middleware/metrics_protection.go:52-54 Composant : Infrastructure — Metrics

Description Le middleware de protection des métriques lit X-Forwarded-For directement depuis la requête et l'utilise pour vérifier l'IP, remplaçant c.ClientIP(). Un attaquant peut forger ce header pour bypasser le whitelist IP.

// Ligne 52-54 — X-Forwarded-For forgeable
clientIP := c.ClientIP()
if forwarded := c.GetHeader("X-Forwarded-For"); forwarded != "" {
    clientIP = strings.TrimSpace(strings.Split(forwarded, ",")[0])
}

Preuve de concept

curl -H "X-Forwarded-For: 127.0.0.1" https://veza.fr/metrics
# Bypasse le whitelist si 127.0.0.1 est autorisé

Impact Information disclosure : un attaquant peut accéder aux métriques Prometheus (pool DB, error rates, endpoints lents, charge système) pour préparer une attaque ciblée.

Remédiation Supprimer la lecture de X-Forwarded-For dans ce middleware. Utiliser uniquement c.ClientIP() qui est déjà configuré pour tenir compte du proxy de confiance (via gin.SetTrustedProxies).

// Supprimer les lignes 52-55, utiliser uniquement :
clientIP := c.ClientIP()

Priorité de correction : Sprint suivant


[MEDIUM-003] : Image Docker ClamAV non pinnée (:latest)

Sévérité : MOYENNE CVSS v3.1 : 4.8 (AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N) CWE : CWE-1104 — Use of Unmaintained Third Party Components OWASP : A06:2021 — Vulnerable and Outdated Components Fichier(s) : docker-compose.yml:60, docker-compose.prod.yml:73 Composant : Infrastructure — Docker

Description L'image ClamAV utilise le tag :latest dans les deux fichiers docker-compose (dev ET production). Cela expose à :

  1. Des breaking changes non testées
  2. Un potentiel supply chain attack (image compromise)
  3. Des builds non reproductibles

Impact Un changement dans l'image ClamAV pourrait casser silencieusement le scan antivirus des uploads, soit en désactivant la protection, soit en bloquant tous les uploads.

Remédiation Pinner l'image à un tag de version spécifique :

clamav:
  image: clamav/clamav:1.4.2  # Vérifier la dernière version stable

Priorité de correction : Sprint suivant


[MEDIUM-004] : Pagination sans limite maximale explicite

Sévérité : MOYENNE CVSS v3.1 : 5.3 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L) CWE : CWE-770 — Allocation of Resources Without Limits OWASP API : API4:2023 — Unrestricted Resource Consumption Fichier(s) : veza-backend-api/internal/pagination/ (à vérifier), handlers multiples Composant : API — Pagination

Description L'audit précédent signalait l'absence de limite maximale explicite sur la pagination. Si un utilisateur envoie ?limit=100000, le serveur pourrait retourner une réponse massive consommant mémoire et bande passante.

Impact Un attaquant peut envoyer des requêtes avec un limit très élevé pour surcharger le serveur (DoS). Impact amplifié si la requête joint plusieurs tables.

Remédiation Ajouter un cap sur le paramètre limit dans le middleware de pagination :

const MaxPageSize = 100
if limit > MaxPageSize {
    limit = MaxPageSize
}

Priorité de correction : Sprint suivant


[MEDIUM-005] : Production JWT utilise HS256 — stream token potentiellement forgeable si secret compromis

Sévérité : MOYENNE (sous-finding de HIGH-002) CVSS v3.1 : 5.9 (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N) CWE : CWE-327 — Use of a Broken or Risky Cryptographic Algorithm OWASP : A02:2021 — Cryptographic Failures Fichier(s) : veza-backend-api/internal/services/jwt_service.go:253-277 Composant : Streaming — Stream Token

Description Le stream token (JWT court, 5 min TTL) pour l'authentification HLS utilise le même secret/clé que le JWT principal. Avec HS256 en production, le compromis du JWT_SECRET permet de forger des stream tokens pour accéder à n'importe quel contenu audio.

Le stream token utilise des claims différents (iss: veza-platform, aud: veza-services) mais la même clé de signature.

Impact Accès non autorisé au streaming audio de tous les contenus de la plateforme.

Remédiation Migrer vers RS256 (cf. HIGH-002). Alternativement, utiliser un secret séparé pour les stream tokens.

Priorité de correction : Sprint suivant (résolu par HIGH-002)


[MEDIUM-006] : CSP unsafe-inline et unsafe-eval pour les routes Swagger

Sévérité : MOYENNE CVSS v3.1 : 4.7 (AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:N/A:N) CWE : CWE-79 — Cross-site Scripting (XSS) OWASP : A05:2021 — Security Misconfiguration Fichier(s) : veza-backend-api/internal/middleware/security_headers.go:78 Composant : Infrastructure — Security Headers

Description Les routes Swagger (/swagger/, /docs/) ont un CSP permissif avec 'unsafe-inline' et 'unsafe-eval' pour le JavaScript. Bien que nécessaire pour le fonctionnement de Swagger UI, cela crée un vecteur XSS si un attaquant peut injecter du contenu dans la documentation Swagger.

csp := "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; ..."

Impact XSS limité aux pages Swagger. L'impact est réduit car Swagger devrait être désactivé en production (déjà le cas selon l'audit précédent).

Remédiation Vérifier que Swagger est effectivement désactivé en production. Ajouter un guard :

if isProd {
    // Ne pas servir Swagger en production
    c.AbortWithStatus(404)
    return
}

Priorité de correction : Backlog


[MEDIUM-007] : Actions CI/CD non pinnées par SHA

Sévérité : MOYENNE CVSS v3.1 : 4.8 (AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N) CWE : CWE-829 — Inclusion of Functionality from Untrusted Control Sphere OWASP : A08:2021 — Software and Data Integrity Failures Fichier(s) : .github/workflows/ci.yml (et tous les workflows) Composant : CI/CD — GitHub Actions

Description Les actions GitHub sont référencées par tag mutable (@v4, @v5, @stable) au lieu de SHA de commit. Un tag peut être déplacé par le mainteneur de l'action, ou en cas de compromission du compte du mainteneur.

Exemples : actions/checkout@v4, actions/setup-node@v4, actions/setup-go@v5, dtolnay/rust-toolchain@stable

Impact Un attaquant compromettant un mainteneur d'action GitHub pourrait injecter du code malveillant dans le pipeline CI (exfiltration de secrets, backdoor dans les artifacts de build).

Remédiation Pinner chaque action par SHA :

# Avant
- uses: actions/checkout@v4
# Après
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11  # v4.1.1

Priorité de correction : Sprint suivant


[MEDIUM-008] : RabbitMQ Management UI exposé en dev

Sévérité : MOYENNE CVSS v3.1 : 5.3 (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) CWE : CWE-668 — Exposure of Resource to Wrong Sphere OWASP : A05:2021 — Security Misconfiguration Fichier(s) : docker-compose.yml:91 Composant : Infrastructure — RabbitMQ

Description Le Management UI de RabbitMQ (port 25672→15672) est exposé sur l'hôte en dev. En production (docker-compose.prod.yml), les ports ne sont pas exposés directement, mais le service utilise toujours l'image rabbitmq:3-management-alpine qui inclut le plugin management.

Impact En dev : accès au dashboard RabbitMQ exposant la topologie des queues et les messages. En prod : si un attaquant accède au réseau Docker, il peut accéder au management UI.

Remédiation

  • Prod : utiliser rabbitmq:3-alpine (sans management) ou désactiver le plugin management
  • Dev : OK si réseau local uniquement

Priorité de correction : Backlog


[LOW-001] : Incohérence politique mot de passe frontend/backend

Sévérité : BASSE CVSS v3.1 : 3.7 (AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N) CWE : CWE-521 — Weak Password Requirements OWASP : A07:2021 — Identification and Authentication Failures ASVS : V2.1.1 Fichier(s) : apps/web/src/lib/passwordValidator.ts vs veza-backend-api/internal/validators/password_validator.go Composant : Authentication — Password Policy

Description L'audit précédent (VEZA-SEC-005) signalait que le frontend accepte 8 caractères alors que le backend exige 12. Si non corrigé, l'utilisateur reçoit une erreur serveur après avoir rempli le formulaire — mauvaise UX.

Remédiation Aligner le frontend sur 12 caractères minimum.

Priorité de correction : Backlog


[LOW-002] : Version Hyperswitch datée (~1 an)

Sévérité : BASSE CVSS v3.1 : 3.1 (AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N) CWE : CWE-1104 — Use of Unmaintained Third Party Components OWASP : A06:2021 — Vulnerable and Outdated Components Fichier(s) : docker-compose.yml:137, docker-compose.prod.yml:117 Composant : Infrastructure — Payments

Description L'image Hyperswitch juspaydotin/hyperswitch-router:2025.01.21.0-standalone date de janvier 2025 (~14 mois). Des correctifs de sécurité et des améliorations de stabilité ont pu être publiés depuis.

Remédiation Mettre à jour vers la dernière version stable d'Hyperswitch après test en staging.

Priorité de correction : Backlog


[LOW-003] : Dépendance Rust dotenv 0.15 obsolète

Sévérité : BASSE CVSS v3.1 : 2.0 (AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:L/A:N) CWE : CWE-1104 — Use of Unmaintained Third Party Components Fichier(s) : veza-stream-server/Cargo.toml Composant : Stream Server — Dependencies

Description dotenv 0.15 date de 2020 et n'est plus maintenu activement. Le fork dotenvy est le successeur recommandé.

Remédiation

# Cargo.toml
dotenvy = "0.15"  # Remplacer dotenv par dotenvy

Et mettre à jour les imports dans le code Rust.

Priorité de correction : Backlog


[LOW-004] : Elasticsearch sans authentification dans le réseau Docker

Sévérité : BASSE CVSS v3.1 : 3.5 (AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) CWE : CWE-306 — Missing Authentication for Critical Function OWASP : A07:2021 — Identification and Authentication Failures Fichier(s) : docker-compose.yml (Elasticsearch si présent), configuration ES Composant : Infrastructure — Elasticsearch

Description Elasticsearch n'a pas d'authentification configurée dans les docker-compose. Tout service du réseau Docker peut accéder aux index et requêter les données directement.

Impact Si un autre container est compromis, l'attaquant peut accéder aux index Elasticsearch contenant potentiellement des données utilisateur (tracks, descriptions, messages indexés).

Remédiation Activer l'authentification native Elasticsearch ou OpenSearch Security.

Priorité de correction : Backlog


[LOW-005] : context.Background() dans les background jobs

Sévérité : BASSE CVSS v3.1 : 2.0 CWE : CWE-404 — Improper Resource Shutdown or Release Fichier(s) : veza-backend-api/internal/jobs/*.go Composant : Background Jobs

Description Les jobs de nettoyage (cleanup_password_reset_tokens, cleanup_sessions, cleanup_hls_segments, cleanup_verification_tokens) utilisent context.Background(). Cela est acceptable pour des background jobs, mais ils devraient utiliser un context dérivé du shutdown manager pour permettre un arrêt gracieux.

Remédiation Passer un context annulable depuis le shutdown manager.

Priorité de correction : Backlog


[LOW-006] : Redis sans mot de passe en développement

Sévérité : BASSE CVSS v3.1 : 2.0 (AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N) CWE : CWE-287 — Improper Authentication Fichier(s) : docker-compose.yml:36-48 Composant : Infrastructure — Redis

Description Redis en dev n'a pas de requirepass. Acceptable en développement local, mais le docker-compose.yml de base ne devrait pas être utilisé tel quel en staging/pré-production.

Impact Limité au développement local. La config production (docker-compose.prod.yml:34) utilise bien requirepass.

Remédiation OK en l'état (déjà protégé en prod). Documenter que docker-compose.yml est strictement pour le dev local.

Priorité de correction : Backlog


[INFO-001] : Bonnes pratiques de sécurité confirmées

Sévérité : INFO (Positif)

Les contrôles de sécurité suivants sont correctement implémentés :

  1. JWT Token Versioning : Révocation immédiate via token_version vérifié contre la DB à chaque requête (auth.go:218)
  2. Token Blacklist Redis : Double vérification avec blacklist Redis quand disponible (auth.go:189)
  3. Session Validation : Triple vérification (JWT signature → token version → session DB) (auth.go:175-260)
  4. Security Headers : Ensemble complet (HSTS, CSP strict pour API, X-Frame-Options DENY, nosniff, Referrer-Policy, Permissions-Policy) (security_headers.go)
  5. CORS Strict : Production requiert whitelist explicite, panic si non configuré (cors.go)
  6. CSRF Protection : Middleware CSRF avec tokens Redis (csrf.go)
  7. Rate Limiting Multi-couche : Global, par IP, par endpoint, par user, upload-specific (rate_limiter.go, ratelimit_redis.go, endpoint_limiter.go)
  8. ClamAV Obligatoire : CLAMAV_REQUIRED=true en production (docker-compose.prod.yml:170)
  9. Bcrypt Cost 12 : Conforme aux recommandations OWASP
  10. Path Validation : ValidateExecPath() sur tous les appels exec.Command (utils/sanitizer.go)
  11. Secret Filtering : Logs filtrés pour les secrets (logging/secret_filter.go)
  12. Audit Trail : Middleware d'audit sur POST/PUT/DELETE (audit.go)
  13. RBAC Middleware : Contrôle d'accès basé sur les rôles avec middleware dédié (rbac_middleware.go)
  14. Ownership Checks : RequireOwnershipOrAdmin sur les ressources utilisateur
  15. Webhook HMAC-SHA512 : Vérification de signature avec comparaison constant-time
  16. Non-root Docker : Container backend tourne en user app:1001
  17. Multi-stage Dockerfile : Build optimisé sans outils de compilation dans l'image finale
  18. GORM : Pas de SQL injection — toutes les queries production utilisent des paramètres préparés
  19. DOMPurify : Sanitisation HTML côté frontend avec whitelist de tags
  20. User Enumeration Protection : Messages d'erreur génériques sur login (pas de "user not found" vs "wrong password")

[INFO-002] : Vérification des correctifs de l'audit précédent

Sévérité : INFO

ID précédent Statut Détail
VEZA-SEC-001 (JWT secret par défaut Rust) CORRIGÉ config_rust.rs:234secret: String::new(), load_from_env exige JWT_SECRET
VEZA-SEC-002 (Issuer/audience mismatch) CORRIGÉ GenerateStreamToken utilise iss: veza-platform, aud: veza-services
VEZA-SEC-003 (Shutdown AppState Rust) ⚠️ À VÉRIFIER Non vérifié dans cet audit
VEZA-SEC-004 (Webhook worker goroutine) ⚠️ À VÉRIFIER Non vérifié dans cet audit
VEZA-SEC-005 (Password policy mismatch) NON CORRIGÉ Repris comme LOW-001
VEZA-SEC-006 (Métriques exposées) CORRIGÉ metrics_protection.go avec bearer token + IP whitelist
VEZA-SEC-007 (context.Background password_reset) ⚠️ À VÉRIFIER Non vérifié dans cet audit
VEZA-SEC-008 (Callback no-op seller) ⚠️ À VÉRIFIER Non vérifié dans cet audit
VEZA-SEC-009 (dotenv obsolète) NON CORRIGÉ Repris comme LOW-003

[INFO-003] : Recommandation — Ajouter un scan de dépendances dans le pipeline

Sévérité : INFO

Le CI inclut déjà govulncheck, cargo audit, et npm audit. Recommandation supplémentaire :

  • Ajouter npm audit --production (exclure les devDeps)
  • Ajouter un check de licence automatisé (ex: license-checker pour npm, golicense pour Go)
  • Configurer Dependabot pour les GitHub Actions elles-mêmes

[INFO-004] : Recommandation — Tests de sécurité automatisés

Sévérité : INFO

Des tests de sécurité existent (tests/security/, tests/integration/webhook_security_test.go). Recommandation :

  • Ajouter des tests de race condition automatisés pour les scénarios marketplace (HIGH-001)
  • Ajouter un test DAST automatisé (OWASP ZAP) dans le pipeline CI/CD
  • Ajouter un test de politique CSP (vérifier que unsafe-inline n'apparaît pas sur les routes non-Swagger)

[INFO-005] : Aucun unsafe dans le code Rust

Sévérité : INFO (Positif)

Aucun bloc unsafe trouvé dans le code applicatif du stream server Rust. Le code utilise exclusivement les abstractions safe de Rust, éliminant les risques de corruption mémoire.


ANALYSE PAR CATÉGORIE OWASP TOP 10

Catégorie Verdict Findings
A01 — Broken Access Control PASS RBAC, ownership checks, CORS strict
A02 — Cryptographic Failures ⚠️ PARTIEL HIGH-002 (HS256 prod), MEDIUM-001 (math/rand 2FA)
A03 — Injection PASS GORM, ValidateExecPath, DOMPurify
A04 — Insecure Design ⚠️ PARTIEL HIGH-001 (race condition), HIGH-003 (context bypass)
A05 — Security Misconfiguration ⚠️ PARTIEL MEDIUM-002, MEDIUM-006, MEDIUM-008
A06 — Vulnerable Components ⚠️ PARTIEL MEDIUM-003, LOW-002, LOW-003
A07 — Auth Failures PASS JWT validation solide, rate limiting, session management
A08 — Software Integrity ⚠️ PARTIEL MEDIUM-007 (CI actions)
A09 — Logging & Monitoring PASS Audit trail, secret filtering, structured logging
A10 — SSRF PASS Pas de SSRF identifié

ANALYSE PAR CATÉGORIE OWASP API TOP 10

Catégorie Verdict Findings
API1 — Broken Object Level Auth PASS RequireOwnershipOrAdmin sur toutes les ressources
API2 — Broken Authentication ⚠️ PARTIEL HIGH-002 (HS256), MEDIUM-001 (math/rand)
API3 — Broken Object Property Auth PASS Validation struct tags, pas de mass assignment
API4 — Unrestricted Resource Consumption ⚠️ PARTIEL MEDIUM-004 (pagination limit)
API5 — Broken Function Level Auth PASS RequireAdmin, RequireRole middleware
API6 — Unrestricted Business Flows ⚠️ PARTIEL HIGH-001 (race condition downloads)
API7 — SSRF PASS Pas de SSRF identifié
API8 — Security Misconfiguration ⚠️ PARTIEL MEDIUM-002, MEDIUM-006
API9 — Improper Inventory PASS API versionnée, pas de endpoints dépréciés exposés
API10 — Unsafe API Consumption PASS Webhook signatures vérifiées

CRITÈRES GO/NO-GO v1.0.0

Critère Statut Détail
Aucun finding CRITIQUE non résolu GO 0 finding critique
Aucun finding HAUT non résolu NO-GO 3 findings HAUTS à corriger
Tous les MOYENS ont un plan de remédiation GO 8 findings avec remédiation documentée
ASVS Level 2 sans FAIL obligatoire ⚠️ CONDITIONNEL Voir checklist ASVS séparée

Décision : NO-GO — Corriger les 3 findings HAUTS avant v1.0.0


Rapport généré le 2026-03-11 par Claude Opus 4.6 Méthodologie : OWASP Top 10 (2021), OWASP API Security Top 10 (2023), ASVS v4.0 Level 2 Référence audit précédent : AUDIT_TECHNIQUE_VEZA_2026-03-04.md