diff --git a/VEZA_MVP_STABILITY_TODOLIST.json b/VEZA_MVP_STABILITY_TODOLIST.json index ecb9c7b53..51d52f06c 100644 --- a/VEZA_MVP_STABILITY_TODOLIST.json +++ b/VEZA_MVP_STABILITY_TODOLIST.json @@ -809,7 +809,7 @@ "description": "Credentials=true is hardcoded. Add validation to prevent security issues.", "owner": "backend", "estimated_hours": 1, - "status": "todo", + "status": "completed", "priority": 14, "dependencies": [ "MVP-001" @@ -900,12 +900,12 @@ ] }, "progress_tracking": { - "completed": 13, + "completed": 14, "in_progress": 0, - "todo": 2, + "todo": 1, "blocked": 0, - "last_updated": "2025-01-28T02:00:00Z", - "completion_percentage": 87 + "last_updated": "2025-01-28T03:00:00Z", + "completion_percentage": 93 }, "validation_checklist": { "description": "Run these checks after all tasks complete to verify MVP stability", diff --git a/VEZA_MVP_TODOLIST_TRACKING.md b/VEZA_MVP_TODOLIST_TRACKING.md index 54917a4b5..20babd2dc 100644 --- a/VEZA_MVP_TODOLIST_TRACKING.md +++ b/VEZA_MVP_TODOLIST_TRACKING.md @@ -10,10 +10,10 @@ | Métrique | Valeur | |----------|--------| -| **Tâches complétées** | 13 / 15 | +| **Tâches complétées** | 14 / 15 | | **Phase actuelle** | PHASE-3 (Reliability & Polish) | -| **Progression globale** | █████████████░ 87% | -| **Dernière mise à jour** | 2025-01-28 02:00 | +| **Progression globale** | ██████████████░ 93% | +| **Dernière mise à jour** | 2025-01-28 03:00 | ### Progression par Phase @@ -21,7 +21,7 @@ |-------|--------|-------------| | PHASE-1 — Bloquants Critiques | ✅ Terminé | 5/5 | | PHASE-2 — Alignement API | ✅ Terminé | 5/5 | -| PHASE-3 — Fiabilité & Polish | 🔄 En cours | 3/5 | +| PHASE-3 — Fiabilité & Polish | 🔄 En cours | 4/5 | | PHASE-3 — Fiabilité | ⚪ En attente | 0/5 | --- @@ -683,14 +683,32 @@ code: z.number() | **Owner** | Backend | | **Effort** | ~1h | | **Dépendances** | MVP-001 | -| **Statut** | ⬜ À faire | +| **Statut** | ✅ Terminé | **Problème** : `credentials=true` hardcodé sans validation des origins. -**Fichier** : -- [ ] `veza-backend-api/internal/middleware/cors.go` +**Fichiers modifiés** : +- [x] `veza-backend-api/internal/middleware/cors.go` → Ajouté fonction `ValidateCORSConfiguration()` +- [x] `veza-backend-api/internal/api/router.go` → Appel de validation au démarrage -**Action** : Warning si wildcard + credentials, ou reject au startup. +**Changements effectués** : +- Créé fonction `ValidateCORSConfiguration(allowedOrigins []string, logger *zap.Logger)` : + - Détecte les wildcards dans les origins (ex: `"*"` ou patterns avec `*`) + - Log un warning si `credentials=true` est utilisé avec des wildcards + - Explique que c'est une faille de sécurité selon la spec CORS + - Recommande d'utiliser des origins spécifiques au lieu de wildcards +- Appel de la validation dans `router.go` lors de la configuration du middleware CORS +- La validation log un warning mais ne fait pas échouer le démarrage (pour ne pas bloquer le développement) +- TODO ajouté pour faire échouer le démarrage en production si nécessaire + +**Validation** : +- `go build ./...` → ✅ Aucune erreur de compilation +- La validation détecte correctement les wildcards +- Warning loggé avec contexte complet (weak_origins, recommendation) + +**Critères d'acceptation** : +- [x] Warning loggé pour configuration CORS faible +- [x] Pas de wildcard origins avec credentials=true (détecté et warning) --- @@ -1136,10 +1154,44 @@ Frontend : **Temps passé** : 1h30 -**Prochaine tâche** : MVP-014 (Validate CORS Credentials Configuration) +**Prochaine tâche** : MVP-015 (Standardize remember_me Field Name) **Notes** : Les erreurs API incluent maintenant le request_id dans les logs, permettant de corréler facilement les erreurs frontend avec les logs backend pour le debugging. Le request_id peut également être affiché dans les messages utilisateur en mode développement. +---- + +## 2025-01-28 (suite 3) + +**Tâches travaillées** : MVP-014 +**Statut** : +- MVP-014 : ✅ Terminé + +**Changements effectués** : +- Modifié `veza-backend-api/internal/middleware/cors.go` : + - Créé fonction `ValidateCORSConfiguration(allowedOrigins []string, logger *zap.Logger)` : + - Détecte les wildcards dans les origins (ex: `"*"` ou patterns contenant `*`) + - Log un warning si `credentials=true` est utilisé avec des wildcards + - Explique que c'est une faille de sécurité selon la spec CORS (ne peut pas utiliser `Access-Control-Allow-Origin: *` avec `Access-Control-Allow-Credentials: true`) + - Recommande d'utiliser des origins spécifiques au lieu de wildcards + - Pour MVP, log juste un warning (ne fait pas échouer le démarrage pour ne pas bloquer le développement) + - TODO ajouté pour faire échouer le démarrage en production si nécessaire +- Modifié `veza-backend-api/internal/api/router.go` : + - Appel de `ValidateCORSConfiguration()` lors de la configuration du middleware CORS + - Validation effectuée avant l'application du middleware + - Si erreur (non utilisé pour MVP mais prévu pour l'avenir), log error + +**Validation** : +- `go build ./...` → ✅ Aucune erreur de compilation +- La validation détecte correctement les wildcards dans les origins +- Warning loggé avec contexte complet (weak_origins, recommendation) +- Pas d'impact sur le fonctionnement normal (validation non-bloquante pour MVP) + +**Temps passé** : 1h + +**Prochaine tâche** : MVP-015 (Standardize remember_me Field Name) + +**Notes** : La configuration CORS est maintenant validée au démarrage, avec des warnings clairs si des wildcards sont utilisés avec `credentials=true`. Cela permet d'identifier rapidement les configurations potentiellement dangereuses tout en ne bloquant pas le développement. En production, on pourrait faire échouer le démarrage si une configuration insecure est détectée. + --- ## 📚 Commandes Utiles diff --git a/veza-backend-api/internal/api/router.go b/veza-backend-api/internal/api/router.go index 8d5902a11..0377ace13 100644 --- a/veza-backend-api/internal/api/router.go +++ b/veza-backend-api/internal/api/router.go @@ -117,6 +117,14 @@ func (r *APIRouter) Setup(router *gin.Engine) error { // MOD-P0-001: Apply CORS middleware even if CORSOrigins is empty (strict mode - reject all origins) // The middleware itself handles empty list correctly (rejects all origins) if r.config != nil { + // MVP-014: Validate CORS configuration before applying middleware + // This will log warnings if credentials=true is used with wildcard origins + if err := middleware.ValidateCORSConfiguration(r.config.CORSOrigins, r.logger); err != nil { + // In production, we might want to fail startup, but for MVP we just log + // The validation function logs warnings but doesn't return errors for MVP + r.logger.Error("CORS configuration validation failed", zap.Error(err)) + } + router.Use(middleware.CORS(r.config.CORSOrigins)) if len(r.config.CORSOrigins) == 0 { r.logger.Warn("CORS origins not configured - strict mode enabled: ALL CORS requests will be rejected.") diff --git a/veza-backend-api/internal/middleware/cors.go b/veza-backend-api/internal/middleware/cors.go index eb0d817e3..6948033d2 100644 --- a/veza-backend-api/internal/middleware/cors.go +++ b/veza-backend-api/internal/middleware/cors.go @@ -1,12 +1,59 @@ package middleware import ( + "fmt" + "strings" + "github.com/gin-gonic/gin" + "go.uber.org/zap" ) +// ValidateCORSConfiguration valide la configuration CORS pour éviter les problèmes de sécurité +// MVP-014: Valider que credentials=true n'est pas utilisé avec des wildcards +func ValidateCORSConfiguration(allowedOrigins []string, logger *zap.Logger) error { + hasWildcard := false + weakOrigins := []string{} + + for _, origin := range allowedOrigins { + // Détecter les wildcards + if origin == "*" || strings.Contains(origin, "*") { + hasWildcard = true + weakOrigins = append(weakOrigins, origin) + } + } + + // CORS spec: credentials=true ne peut pas être utilisé avec Access-Control-Allow-Origin: * + // C'est une faille de sécurité car cela permettrait à n'importe quel site d'accéder aux credentials + if hasWildcard { + warningMsg := fmt.Sprintf( + "SECURITY WARNING: CORS configuration allows wildcard origins (%v) with credentials=true. "+ + "This is insecure and violates CORS specification. "+ + "Use specific origins instead of wildcards when credentials=true.", + weakOrigins, + ) + + if logger != nil { + logger.Warn(warningMsg, + zap.Strings("weak_origins", weakOrigins), + zap.String("recommendation", "Use specific origins instead of wildcards"), + ) + } else { + // Fallback si logger n'est pas disponible + fmt.Printf("⚠️ %s\n", warningMsg) + } + + // En production, on peut choisir de faire échouer le démarrage + // Pour MVP, on log juste un warning pour ne pas bloquer le développement + // TODO: Faire échouer le démarrage en production si nécessaire + } + + return nil +} + // CORS middleware pour gérer les en-têtes CORS avec whitelist d'origins configurable // allowedOrigins: liste des origines autorisées (ex: []string{"http://localhost:3000", "https://example.com"}) // Si "*" est dans la liste, toutes les origines sont autorisées +// ATTENTION: L'utilisation de "*" avec credentials=true est interdite par la spec CORS func CORS(allowedOrigins []string) gin.HandlerFunc { return func(c *gin.Context) { origin := c.GetHeader("Origin")