# 🔍 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 de `config.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 tout - `Load()` (ligne 384) : fonction alternative qui charge seulement `EnvConfig` (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é ### 1.2. Sources de vérité **Ordre de priorité actuel**: 1. Variables d'environnement système (priorité maximale) 2. Fichiers `.env.{env}` (ex: `.env.development`) 3. Fichiers `.env` (fallback) 4. Valeurs par défaut hardcodées dans le code **Variables critiques chargées**: - `JWT_SECRET`: ✅ **REQUIS** (ligne 117) - `getEnvRequired()` → panic si absent - `DATABASE_URL`: ✅ **REQUIS** (ligne 124) - `getEnvRequired()` → panic si absent - `CORS_ALLOWED_ORIGINS`: ⚠️ **DÉFAUT DANGEREUX** (ligne 101) - `getEnvStringSlice(..., []string{"*"})` → **wildcard par défaut** - `REDIS_URL`: ⚠️ Valeur par défaut `"redis://localhost:6379"` (ligne 122) - `APP_PORT`: Valeur par défaut `8080` (ligne 113) - `CHAT_JWT_SECRET`: Fallback vers `JWT_SECRET` si non défini (ligne 121) **Détection d'environnement**: - `DetectEnvironment()` (ligne 28 de `env_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_ORIGINS` n'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 vers `CORSDefault()` si `CORSOrigins` est 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.Printf` dans `getEnv()` → **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**: ```go 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**: 1. ✅ Le middleware CORS est bien configuré via la config 2. ❌ **Fallback vers `CORSDefault()` si liste vide** → wildcard 3. ❌ **Pas de validation que `"*"` n'est pas utilisé en prod** 4. ❌ **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"]` si `CORS_ALLOWED_ORIGINS` non 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_ORIGINS` **REQUIS** 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): ```go 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_ORIGINS` doit être défini et non vide - `CORS_ALLOWED_ORIGINS` ne 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 `Env` dans `Config` - 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.