- CI: workflows updates (cd, ci), remove playwright.yml - E2E: global-setup, auth/playlists/profile specs - Remove playwright-report and test-results artifacts from tracking - Backend: auth, handlers, services, workers, migrations - Frontend: components, features, vite config - Add e2e-results.json to gitignore - Docs: REMEDIATION_PROGRESS, audit archive - Rust: chat-server, stream-server updates
7.9 KiB
7.9 KiB
🔍 AUDIT DE SÉCURITÉ - Configuration Backend Go
Date: 2025-01-XX
Fichiers analysés: internal/config/config.go, internal/api/router.go, internal/middleware/cors.go
1. STRUCTURE ACTUELLE
1.1. Représentation de la configuration
-
Struct principale:
config.Config(ligne 24-79 deconfig.go)- Mélange de services initialisés (Database, Redis, Services, Middlewares) et de valeurs de configuration (AppPort, JWTSecret, CORSOrigins, etc.)
- Pattern: Singleton créé via
NewConfig()qui initialise tout (DB, Redis, Services, Middlewares)
-
Initialisation:
NewConfig()(ligne 82) : fonction globale qui charge toutLoad()(ligne 384) : fonction alternative qui charge seulementEnvConfig(struct plus simple)- Problème: Deux chemins de chargement différents, confusion possible
-
Variables globales:
- Pas de variables globales explicites, mais
NewConfig()crée un singleton qui est passé partout - Pattern acceptable mais peut être amélioré
- Pas de variables globales explicites, mais
1.2. Sources de vérité
Ordre de priorité actuel:
- Variables d'environnement système (priorité maximale)
- Fichiers
.env.{env}(ex:.env.development) - Fichiers
.env(fallback) - Valeurs par défaut hardcodées dans le code
Variables critiques chargées:
JWT_SECRET: ✅ REQUIS (ligne 117) -getEnvRequired()→ panic si absentDATABASE_URL: ✅ REQUIS (ligne 124) -getEnvRequired()→ panic si absentCORS_ALLOWED_ORIGINS: ⚠️ DÉFAUT DANGEREUX (ligne 101) -getEnvStringSlice(..., []string{"*"})→ wildcard par défautREDIS_URL: ⚠️ Valeur par défaut"redis://localhost:6379"(ligne 122)APP_PORT: Valeur par défaut8080(ligne 113)CHAT_JWT_SECRET: Fallback versJWT_SECRETsi non défini (ligne 121)
Détection d'environnement:
DetectEnvironment()(ligne 28 deenv_detection.go): Priorité APP_ENV > NODE_ENV > GO_ENV > hostname > development- Problème: L'environnement est détecté mais pas utilisé pour différencier les comportements (CORS, validation, etc.)
1.3. Points de risque sécurité identifiés
🔴 CRITIQUE - CORS Wildcard par défaut
- Ligne 101 de
config.go:corsOrigins := getEnvStringSlice("CORS_ALLOWED_ORIGINS", []string{"*"}) - Impact: Si
CORS_ALLOWED_ORIGINSn'est pas défini, toutes les origines sont autorisées - Risque: En production, si la variable est oubliée, l'API accepte les requêtes de n'importe quel domaine
- Ligne 62 de
router.go: Fallback versCORSDefault()siCORSOriginsest vide → double risque
🟠 MOYEN - Pas de validation CORS selon environnement
- Ligne 483-544 de
config.go:Validate()ne vérifie pas que CORS n'est pas"*"en production - Impact: Aucune protection contre le wildcard en prod
- Risque: Configuration dangereuse peut passer inaperçue
🟠 MOYEN - Valeurs par défaut trop permissives
REDIS_URL: Valeur par défaut hardcodée (acceptable en dev, dangereux si oublié en prod)APP_PORT: Valeur par défaut (acceptable)- Impact: En prod, si variables manquantes, l'app démarre avec des valeurs dev
🟡 FAIBLE - Pas de distinction dev/test/prod
- L'environnement est détecté mais pas utilisé pour:
- Changer les defaults CORS
- Valider différemment selon l'env
- Refuser de démarrer si config critique manque en prod
🟡 FAIBLE - Debug logs potentiels en prod
- Ligne 417-420 de
config.go:fmt.PrintfdansgetEnv()→ logs de debug en production - Impact: Fuite d'information sur les valeurs de config (même si masquées ailleurs)
1.4. Configuration CORS
Fichier: internal/middleware/cors.go
- Fonction
CORS(allowedOrigins []string):- Accepte une liste d'origines
- Si
"*"est dans la liste → toutes les origines autorisées (ligne 36) - Headers autorisés:
Authorization, Content-Type(ligne 20) - Méthodes autorisées:
GET, POST, PUT, DELETE, OPTIONS(ligne 19) Access-Control-Allow-Credentials: true(ligne 21)
Fichier: internal/api/router.go
- Ligne 59-63:
if r.config != nil && len(r.config.CORSOrigins) > 0 { router.Use(middleware.CORS(r.config.CORSOrigins)) } else { router.Use(middleware.CORSDefault()) // ← DANGER: wildcard par défaut }
Problèmes identifiés:
- ✅ Le middleware CORS est bien configuré via la config
- ❌ Fallback vers
CORSDefault()si liste vide → wildcard - ❌ Pas de validation que
"*"n'est pas utilisé en prod - ❌ Pas de distinction dev/prod pour les origines par défaut
2. DESIGN CIBLE PROPOSÉ
2.1. Profils d'environnement
Environnements supportés:
development: Logs verbeux, CORS permissif (localhost uniquement)test: Config adaptée aux tests (DB test, pas de side-effects)production: Strict - aucune valeur par défaut dangereuse, validation stricte
2.2. Comportements attendus
Development
- CORS par défaut:
["http://localhost:3000", "http://127.0.0.1:3000"]siCORS_ALLOWED_ORIGINSnon défini - Logs: DEBUG/INFO
- Validation: Permissive (valeurs par défaut acceptées)
Test
- CORS: Liste vide ou configurée explicitement
- DB: URL de test requise
- Validation: Stricte mais adaptée aux tests
Production
- CORS:
CORS_ALLOWED_ORIGINSREQUIS et non vide - CORS: Interdiction explicite de
"*"en prod - Validation: Erreur fatale si variables critiques manquantes
- Logs: INFO/WARN/ERROR uniquement (pas de DEBUG)
2.3. Chargement de la config
Fonction unique: LoadConfigFromEnv() (*AppConfig, error)
- Charge depuis variables d'environnement uniquement
- Valide selon l'environnement détecté
- Retourne erreur si config invalide en prod
Struct simplifiée (pour la partie config pure):
type AppConfig struct {
Env string // development, test, production
HttpPort string
DatabaseURL string
RedisURL string
JwtSecret string
ChatJWTSecret string
CorsAllowedOrigins []string
// ... autres champs
}
2.4. Validation renforcée
Nouvelle fonction: ValidateForEnvironment(cfg *AppConfig) error
- En production:
CORS_ALLOWED_ORIGINSdoit être défini et non videCORS_ALLOWED_ORIGINSne doit pas contenir"*"- Toutes les variables critiques doivent être présentes
- En development:
- Valeurs par défaut acceptées
- Warning si config incomplète mais démarrage autorisé
3. PLAN D'IMPLÉMENTATION
Étape 1: Refactor config.go
- Ajouter champ
EnvdansConfig - Modifier
NewConfig()pour utiliser l'environnement détecté - Créer
validateForEnvironment()avec règles strictes selon env - Modifier defaults CORS selon environnement
Étape 2: Mettre à jour router.go
- Supprimer fallback
CORSDefault() - Utiliser strictement
config.CorsAllowedOrigins - Ajouter validation au démarrage
Étape 3: Tests
- Test dev avec defaults
- Test prod avec CORS manquant → erreur
- Test prod avec CORS="*" → erreur
- Test prod valide
Étape 4: Documentation
- Créer
docs/BACKEND_CONFIG.md - Lister variables d'environnement
- Expliquer différences dev/prod
4. RÉSUMÉ DES RISQUES
| Risque | Sévérité | Fichier | Ligne | Action requise |
|---|---|---|---|---|
| CORS wildcard par défaut | 🔴 CRITIQUE | config.go | 101 | Valeur par défaut selon env |
| Fallback CORSDefault() | 🔴 CRITIQUE | router.go | 62 | Supprimer, erreur si vide |
| Pas de validation CORS prod | 🟠 MOYEN | config.go | 483 | Ajouter validation selon env |
| Debug logs en prod | 🟡 FAIBLE | config.go | 417 | Supprimer fmt.Printf |
| Pas de distinction dev/prod | 🟡 FAIBLE | config.go | 82 | Utiliser env détecté |
Prochaines étapes: Implémentation des corrections identifiées.