Expanded from initial 14-finding analysis to full 36 findings after 6 specialized audit agents completed deep analysis. - PENTEST_REPORT: 5 CRITICAL, 10 HIGH, 12 MEDIUM, 6 LOW, 3 INFO - REMEDIATION_MATRIX: P0 (6h), P1 (17h), P2 (8h), P3 (10h) = ~41h total - ASVS_CHECKLIST: 70/102 (68.6%) with 5 FAIL, 26 PARTIAL Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 KiB
10 KiB
Matrice de Remédiation — VEZA v0.12.6
Date : 2026-03-13 Référence : PENTEST_REPORT_VEZA_v0.12.6.md (36 findings)
Priorité de remédiation
Les actions sont classées par priorité d'implémentation (combinaison sévérité + facilité de fix + impact business).
Actions Critiques (P0 — Immédiat, avant tout déploiement)
| ID | Finding | Sévérité | Fichier(s) | Action | Effort |
|---|---|---|---|---|---|
| REM-001 | CRIT-001 | CRITICAL | chat_websocket_handler.go:50, playback_websocket_handler.go:106, co_listening_websocket_handler.go:105 |
Supprimer InsecureSkipVerify: true. Implémenter OriginPatterns avec whitelist des domaines autorisés. |
1h |
| REM-002 | CRIT-002 | CRITICAL | marketplace/payout.go:175-195 |
Déplacer GetSellerBalance DANS la transaction avec SELECT FOR UPDATE (clause.Locking{Strength: "UPDATE"}) avant validation du montant. |
2h |
| REM-003 | CRIT-003 | CRITICAL | marketplace/service.go:1136-1189 |
Wrapper lecture + validation + refund dans une seule transaction avec SELECT FOR UPDATE sur l'order. Vérifier order.Status != "refunded" atomiquement. |
2h |
| REM-004 | CRIT-004 | CRITICAL | analytics/handler.go:727-777 |
Ajouter vérification track.CreatorID == userID avant de retourner les analytics. Retourner 403 sinon. |
30min |
| REM-005 | CRIT-005 | CRITICAL | handlers/marketplace.go:285-290 |
Remplacer filepath.Join(previewDir, file.Filename) par filepath.Join(previewDir, filepath.Base(file.Filename)) ou générer un UUID. |
15min |
Effort total P0 : ~6h
Actions Prioritaires (P1 — Avant release v1.0.0)
| ID | Finding | Sévérité | Fichier(s) | Action | Effort |
|---|---|---|---|---|---|
| REM-006 | HIGH-001 | HIGH | handlers/common.go:601-610 |
Remplacer c.GetHeader("X-Forwarded-For") par c.ClientIP() + configurer SetTrustedProxies() |
1h |
| REM-007 | HIGH-002 | HIGH | user_service.go:75, social_service.go:321, types/stats.go:31, social/models.go:32 |
Supprimer followers_count/following_count de PublicUserResponse et SuggestionUser. Ajouter json:"-" sur LikeCount du modèle Post. |
2h |
| REM-008 | HIGH-003 | HIGH | api/user/handler.go:75-95, api/user/service.go:188-267 |
Filtrer les champs autorisés par rôle dans UpdateMe(). Seuls les admins peuvent modifier role, is_verified, is_active. |
1h |
| REM-009 | HIGH-004 | HIGH | handlers/live_stream_callback.go:26-84 |
Implémenter HMAC-SHA256 avec timestamp + body dans la signature RTMP callback. | 2h |
| REM-010 | HIGH-005 | HIGH | auth/service.go:653-707 |
Combiner validate + rotate du refresh token dans une seule transaction DB atomique. | 2h |
| REM-011 | HIGH-006 | HIGH | marketplace/service.go:464, 764-787 |
Effectuer validation et incrémentation used_count du promo code dans la même transaction avec SELECT FOR UPDATE. |
1h |
| REM-012 | HIGH-007 | HIGH | veza-stream-server/src/auth/token_validator.rs:100-138 |
Ajouter un nonce ou stocker les tokens consommés dans Redis avec TTL pour empêcher le replay. | 3h |
| REM-013 | HIGH-008 | HIGH | handlers/account_deletion_handler.go:75-135 |
Ajouter nettoyage GDPR pour orders (buyer), licenses, seller payouts, seller balance, seller transfers. Anonymiser plutôt que supprimer. | 3h |
| REM-014 | HIGH-009 | HIGH | marketplace/service.go:610-676 |
Dans ProcessPaymentWebhook(), comparer order.TotalAmount avec le montant reçu du webhook avant traitement. |
1h |
| REM-015 | HIGH-010 | HIGH | subscription/service.go:237-251 |
Déplacer la vérification du trial gratuit (previousTrialCount) dans la transaction avec SELECT FOR UPDATE sur le user. |
1h |
Effort total P1 : ~17h
Actions Recommandées (P2 — Sprint suivant)
| ID | Finding | Sévérité | Fichier(s) | Action | Effort |
|---|---|---|---|---|---|
| REM-016 | MEDIUM-001 | MEDIUM | auth/service.go:156, :986 |
Remplacer bcrypt.DefaultCost par bcryptCost (12) importé depuis password_service.go ou une constante partagée. |
30min |
| REM-017 | MEDIUM-002 | MEDIUM | sast.yml, security-scan.yml, cd.yml, stream-ci.yml, container-scan.yml, staging-validation.yml |
Épingler les 12+ GitHub Actions par SHA. Configurer Dependabot pour les mises à jour. | 2h |
| REM-018 | MEDIUM-003 | MEDIUM | .env.production:40 |
Renommer en .env.local ou .env.development. Mettre les valeurs HTTPS par défaut. Ajouter validation au startup. |
1h |
| REM-019 | MEDIUM-004 | MEDIUM | docker-compose.yml:296 |
Supprimer mc anonymous set download. Configurer des politiques MinIO par bucket avec accès authenticated uniquement. |
30min |
| REM-020 | MEDIUM-005 | MEDIUM | api/user/handler.go, core/admin/handler.go, ~15 handlers |
Ajouter max(limit, 100) sur tous les endpoints paginés. Créer un helper SanitizePagination(). |
2h |
| REM-021 | MEDIUM-006 | MEDIUM | handlers/marketplace.go:270-289 |
Ajouter vérification file.Size avant sauvegarde dans le handler marketplace upload. |
15min |
| REM-022 | MEDIUM-007 | MEDIUM | infra/nginx-rtmp/nginx.conf:46 |
Remplacer Access-Control-Allow-Origin: * par la whitelist de domaines autorisés. |
15min |
| REM-023 | MEDIUM-008 | MEDIUM | docker-compose.yml:35-56 |
Ajouter --requirepass ${REDIS_PASSWORD} même en développement. |
15min |
| REM-024 | MEDIUM-009 | MEDIUM | apps/web/nginx.production.conf:11-14 |
Ajouter Strict-Transport-Security header dans la config nginx production frontend. |
15min |
| REM-025 | MEDIUM-010 | MEDIUM | playback_websocket_handler.go:138-152 |
Ajouter conn.SetReadLimit(maxMessageSize) pour limiter la taille des messages WebSocket. |
15min |
| REM-026 | MEDIUM-011 | MEDIUM | marketplace/service.go:806-840 |
Vérifier license.ExpiresAt avant de servir le téléchargement. Retourner 403 si expirée. |
30min |
| REM-027 | MEDIUM-012 | MEDIUM | cmd/api/main.go:8 |
Conditionner import _ "net/http/pprof" derrière un build tag //go:build debug ou un flag d'environnement. |
30min |
Effort total P2 : ~8h
Actions Optionnelles (P3 — Backlog)
| ID | Finding | Sévérité | Fichier(s) | Action | Effort |
|---|---|---|---|---|---|
| REM-028 | LOW-001 | LOW | config/config.go:138 |
Passer CookieSameSite de lax à strict si pas de flow OAuth redirect cross-site. |
30min |
| REM-029 | LOW-002 | LOW | migrations/*.sql |
Auditer les 30+ CASCADE DELETE. Remplacer par RESTRICT/SET NULL pour orders, payments, subscriptions. | 4h |
| REM-030 | LOW-003 | LOW | utils/utils.go:57 |
Aligner HashPassword() sur bcryptCost = 12 ou la supprimer si non utilisée en prod. |
15min |
| REM-031 | LOW-004 | LOW | staging-validation.yml:35 |
Épingler docker/setup-buildx-action par SHA. |
10min |
| REM-032 | LOW-005 | LOW | veza-backend-api/Dockerfile:28, veza-stream-server/Dockerfile:29 |
Remplacer :latest par des tags de version spécifiques dans les Dockerfiles dev. |
15min |
| REM-033 | LOW-006 | LOW | docker-compose.yml:171 |
Remplacer le JWT_SECRET hardcodé par une variable d'environnement obligatoire, même en dev. | 15min |
| REM-034 | INFO-001 | INFO | veza_back_api_db/ |
Ajouter au .gitignore, purger de l'historique git avec BFG. |
1h |
| REM-035 | INFO-002 | INFO | cmd/tools/hash_gen/main.go:11, cmd/tools/create_test_user/main.go:54,72 |
Aligner sur bcryptCost = 12. |
15min |
| REM-036 | INFO-003 | INFO | services/jwt_service.go |
Ajouter kid header dans les JWT et support multi-clés pour faciliter la rotation. |
3h |
Effort total P3 : ~10h
Résumé par effort
| Priorité | Findings | Effort total |
|---|---|---|
| P0 (Immédiat — bloquant) | 5 CRITICAL | ~6h |
| P1 (Avant v1.0.0) | 10 HIGH | ~17h |
| P2 (Sprint suivant) | 12 MEDIUM | ~8h |
| P3 (Backlog) | 9 LOW/INFO | ~10h |
| Total | 36 | ~41h |
Workflow de remédiation
── P0 CRITICAL (Jour 1) ──────────────────────────────────
1. REM-005 (Path traversal) → Test: upload fichier avec ../ dans le nom
2. REM-004 (Analytics IDOR) → Test: accéder aux analytics d'une track d'un autre user
3. REM-001 (WebSocket CSWSH) → Test: connexion WS depuis un domaine non autorisé
4. REM-002 (Payout race) → Test: 2 payouts simultanés, vérifier solde cohérent
5. REM-003 (Refund race) → Test: 2 refunds simultanés, vérifier un seul traité
── P1 HIGH (Semaine 1) ───────────────────────────────────
6. REM-006 (IP spoofing) → Test: rate limit avec X-Forwarded-For forgé
7. REM-007 (Popularity metrics) → Test: /api/v1/users/:id ne retourne plus followers_count
8. REM-008 (Mass assignment) → Test: PUT /api/v1/users/me avec {"role":"admin"} = rejeté
9. REM-010 (Refresh token race) → Test: 2 refresh simultanés, un seul réussit
10. REM-014 (Webhook amount) → Test: webhook avec montant différent = rejeté
11. REM-011 (Promo code race) → Test: 2 uses simultanées, max_uses respecté
12. REM-015 (Free trial race) → Test: 2 souscriptions trial simultanées, une seule OK
13. REM-009 (RTMP auth) → Test: callback avec signature invalide = rejeté
14. REM-012 (Stream replay) → Test: URL rejouée après consommation = rejetée
15. REM-013 (GDPR financier) → Test: suppression compte, vérifier données financières anonymisées
── P2 MEDIUM (Sprint suivant) ────────────────────────────
16-27. REM-016 à REM-027 → Tests spécifiques par finding
Métriques de suivi
| Métrique | Valeur actuelle | Cible v1.0.0 |
|---|---|---|
| Findings CRITICAL | 5 | 0 |
| Findings HIGH | 10 | 0 |
| Findings MEDIUM | 12 | 0 |
| Findings LOW | 6 | ≤ 2 |
| Findings INFO | 3 | ≤ 3 |
| Race conditions financières | 4 (payout, refund, promo, trial) | 0 |
| WebSocket origin validation | 0/3 handlers | 3/3 handlers |
| Actions pinned by SHA | ~60% | 100% |
| bcrypt cost consistency | 2 valeurs (10, 12) | 1 valeur (12) |
| Public popularity metrics | 3 endpoints | 0 endpoints |
| IDOR vulnerabilities | 1 (analytics) | 0 |
Matrice générée le 2026-03-13 — VEZA v0.12.6 — 36 findings