veza/apps/web/dev_audit/frontend/06_security_frontend.md

186 lines
7.3 KiB
Markdown
Raw Normal View History

# PHASE F — SÉCURITÉ FRONTEND
---
## F1. Secrets et données sensibles
### Variables VITE_* exposées au bundle
| Variable | Sensible ? | Verdict |
|----------|-----------|---------|
| `VITE_API_URL` | ❌ Non — URL publique | ✅ OK |
| `VITE_WS_URL` | ❌ Non — URL publique | ✅ OK |
| `VITE_STREAM_URL` | ❌ Non — URL publique | ✅ OK |
| `VITE_UPLOAD_URL` | ❌ Non — URL publique | ✅ OK |
| `VITE_APP_NAME` | ❌ Non — branding | ✅ OK |
| `VITE_DEBUG` | ⚠️ Potentiel — active le debug | ⚠️ S'assurer false en prod |
| `VITE_USE_MSW` | ⚠️ Potentiel — active le mocking | ⚠️ S'assurer false en prod |
| `VITE_FCM_VAPID_KEY` | ⚠️ Limité — clé publique Firebase | ✅ OK (clé publique par design) |
| `VITE_FEATURE_*` | ❌ Non — feature flags | ✅ OK |
| `VITE_SENTRY_DSN` | ❌ Non — DSN public par design | ✅ OK |
| `VITE_DOMAIN` | ❌ Non — domaine public | ✅ OK |
### Secrets dans le code source
-**Aucun secret hardcodé** détecté dans le code source
- ✅ Tokens de test uniquement dans les fichiers mock (`mocks/handlers.ts`)
- ✅ Pas de clés API, mots de passe, ou secrets privés
### Fichiers .env
| Fichier | Tracké | Verdict |
|---------|--------|---------|
| `.env.example` | ✅ Tracké (template) | ✅ OK |
| `.env.local` | ❌ Non tracké | ✅ OK |
| `.env.storybook` | ✅ Tracké | ⚠️ Vérifier qu'il ne contient pas de secrets |
| `.env.production` | ✅ Tracké | ⚠️ Vérifier qu'il ne contient pas de secrets réels |
### Stockage JWT
-**httpOnly cookies** — tokens JWT stockés dans des cookies httpOnly par le backend [services/tokenStorage.ts]
- ✅ JavaScript ne peut pas lire les tokens (getters retournent `null`)
- ✅ Nettoyage des vestiges localStorage inclus
-**Excellente pratique de sécurité**
---
## F2. XSS
### dangerouslySetInnerHTML
| Fichier | Ligne | Source des données | Sanitization | Verdict |
|---------|-------|-------------------|-------------|---------|
| `features/chat/components/ChatMessages.tsx` | 145 | `message.content` (user input) | ✅ `sanitizeChatMessage()` | ✅ Sûr |
| `features/chat/components/virtualized-chat-messages/VirtualizedChatMessageItem.tsx` | 58 | `message.content` (user input) | ✅ `sanitizeChatMessage()` | ✅ Sûr |
### Implémentation de la sanitization
**Fichier** : `utils/sanitize.ts` (429 lignes)
**Configuration DOMPurify** :
- Tags autorisés : `p, br, strong, em, u, i, b, span, a`
- Attributs autorisés : `class, href, title, target`
- URI schemes autorisés : `http, https, mailto` uniquement
- Tags interdits : `script, iframe, object, embed, form, input, button`
- Attributs interdits : `onerror, onload, onclick, onmouseover, onfocus, onblur`
- Fallback de sanitization manuelle si DOMPurify indisponible
**Verdict** : ✅ **Robuste**. La sanitization est correctement implémentée avec DOMPurify et une configuration restrictive.
### Autres vecteurs XSS
-**Aucun `eval()`** ou `new Function()` détecté
-**Aucun `.innerHTML =`** direct
-**Aucun `document.write`**
- ✅ React échappe automatiquement le rendu JSX par défaut
---
## F3. Stockage client
### localStorage
| Donnée | Fichier | Sensible ? | Verdict |
|--------|---------|-----------|---------|
| Density preference | `features/tracks/components/TrackGrid.tsx:60,84` | ❌ Non | ✅ OK |
| (Legacy token cleanup) | `services/tokenStorage.ts` | — | ✅ Nettoyé |
### sessionStorage
| Donnée | Fichier | Sensible ? | Verdict |
|--------|---------|-----------|---------|
| Deprecation warnings | `services/api/client.ts:773-774,872-884` | ❌ Non | ✅ OK |
| API error tracking | `services/api/client.ts:1347` | ❌ Non | ✅ OK |
**Verdict** : ✅ Aucune donnée sensible en localStorage/sessionStorage. Les tokens sont dans des cookies httpOnly.
---
## F4. Dépendances
### Build cassé
- 🔴 **Le build échoue** : `educationService` manquant (import fantôme dans `useEducationView.ts`)
- Cela empêche l'exécution de `npm audit` sur un build propre
### Dépendances notables
| Dépendance | Version | Risque |
|------------|---------|--------|
| `dompurify` | ^3.3.0 | ✅ Dernière version — sanitization XSS |
| `axios` | ^1.13.5 | ✅ Récent |
| `react` | ^18.2.0 | ✅ Stable |
| `zod` | ^3.25.76 | ✅ Validation schema |
| `swagger-ui-react` | ^5.31.0 | ⚠️ En prod deps — potentiel d'attaque via UI Swagger exposée |
| `lucide-react` | ^0.321.0 | ⚠️ Version ancienne (2024) — mise à jour recommandée |
---
## F5. Autres vecteurs
### CORS
- ✅ Proxy configuré en dev (`vite.config.ts`) — pas de CORS issues en dev
-`withCredentials: true` dans le client Axios pour les cookies
- [DONNÉES INSUFFISANTES — CORS headers côté serveur non analysés]
### CSP
-**Utilitaire CSP présent** (`utils/csp.ts`)
- ✅ Production CSP utilise des nonces (pas de `unsafe-inline` pour scripts)
- ✅ Dev CSP autorise `unsafe-eval` pour Vite HMR uniquement
- ⚠️ Les headers CSP doivent être injectés côté serveur — vérifier l'intégration
### CSRF
-**Implémenté** (`services/csrf.ts`)
- ✅ Token CSRF récupéré depuis `/csrf-token` endpoint
- ✅ Stocké en mémoire (pas en localStorage)
- ✅ Header `X-CSRF-Token` injecté via intercepteur Axios
- ✅ Mécanisme de refresh avec déduplification
### Open redirects
-**Aucune assignation `window.location =` détectée** avec input utilisateur
- ✅ Navigation via React Router uniquement
### Prototype pollution
- ✅ Pas d'usage de `lodash.merge` ou patterns similaires dangereux détectés
---
## Classement des vulnérabilités
| Gravité | Vulnérabilité | Localisation | Exploitabilité | Urgence |
|---------|--------------|--------------|----------------|---------|
| 🟡 MOYENNE | Build cassé — import fantôme bloque le build | `useEducationView.ts``educationService` | Non exploitable (build-time) | 🔴 Immédiate — bloque le déploiement |
| 🟡 MOYENNE | `VITE_DEBUG` / `VITE_USE_MSW` en production | Config env | Faible — info disclosure | ⚠️ Vérifier les valeurs en prod |
| 🟡 MOYENNE | Swagger UI en production deps | `package.json` | Faible — surface d'attaque via Swagger UI | ⚠️ Déplacer en devDependencies ou lazy-load |
| 🟢 BASSE | `.env.production` tracké | `.env.production` | Très faible — si ne contient que des valeurs publiques | 🟢 Vérifier le contenu |
| 🟢 BASSE | CSP headers non vérifiés côté serveur | Server config | Dépend du serveur | 🟢 Audit serveur nécessaire |
---
## SCORE SÉCURITÉ : 8/10
### Points gagnés
| Point | Score | Justification |
|-------|-------|---------------|
| JWT httpOnly cookies | +2.0 | Excellente pratique — tokens inaccessibles au JS |
| XSS sanitization | +1.5 | DOMPurify strict, pas d'eval, pas d'innerHTML |
| CSRF protection | +1.5 | Token CSRF en mémoire, header injection |
| Pas de secrets hardcodés | +1.0 | Aucun secret dans le code source |
| CSP utilities | +0.5 | Utilitaire prêt avec nonces |
| No open redirects | +0.5 | Navigation React Router uniquement |
| No prototype pollution | +0.5 | Pas de patterns dangereux |
### Points perdus
| Point | Score | Justification |
|-------|-------|---------------|
| Build cassé | -0.5 | Import fantôme bloque le déploiement |
| Swagger UI en prod deps | -0.3 | Surface d'attaque potentielle |
| Debug flags en env | -0.2 | VITE_DEBUG pourrait être activé en prod |