From a0b11c7b5f55e70019bfbb741a4d7ef3929c9bb5 Mon Sep 17 00:00:00 2001 From: alma Date: Fri, 16 Jan 2026 23:24:37 +0100 Subject: [PATCH] Fondation --- .DS_Store | Bin 10244 -> 10244 bytes AUDIT_COMPLET.md | 1217 -------------------------- FILES_TO_DELETE.md | 36 - app/api/courrier/account/route.ts | 17 +- keycloak-user-creation-workflow.json | 338 ------- 5 files changed, 9 insertions(+), 1599 deletions(-) delete mode 100644 AUDIT_COMPLET.md delete mode 100644 FILES_TO_DELETE.md delete mode 100644 keycloak-user-creation-workflow.json diff --git a/.DS_Store b/.DS_Store index 680a9f9d5b4154bccd590af49ae6e98b41cf766a..af8838991ba468a1b3b087de03a42aa4837bcd35 100644 GIT binary patch delta 141 zcmZn(XbG6$gHU^hRb@?;(XO+^6)M}|-a7Y0v;5QcaLX9j-;Uxok%9|l(-UymV| zA!YI_0r}0Q0yh{Z%L*G<3Ng3=m4c*$fyzUG%Hx5WU7;FWAzD0h@{^Nt@{<@C7z7v? c7=Hq3z0FR-M|mbT^lWBV_{FlhSCp9<0D|8i)c^nh delta 143 zcmZn(XbG6$C7U^hRb%48k^&CR6(Hy90B7*ZJW8Il=_J#+GtlXCKt7#J7?7#J9T zGB7Zm`ws>{5e5dhy2(|d4I)P7COQhn=4Q1z3e}cI2098R#%7cG#EeDZ%F2R^@^bR? c(t%nTCwmDQZ$2ori)S;t!Y`K1r6SDC0Iv%upa1{> diff --git a/AUDIT_COMPLET.md b/AUDIT_COMPLET.md deleted file mode 100644 index 468b8c3..0000000 --- a/AUDIT_COMPLET.md +++ /dev/null @@ -1,1217 +0,0 @@ -# 🔍 AUDIT COMPLET - PROJET NEAH -## Next.js 16.1.1 (App Router) - Audit Performance, Qualité, Sécurité & RGPD - -**Date de l'audit :** $(date) -**Version Next.js :** 16.1.1 -**Architecture :** App Router -**TypeScript :** ✅ Activé - ---- - -## 📊 RÉSUMÉ EXÉCUTIF - -| Catégorie | Score | Statut | -|-----------|-------|--------| -| **Performance** | 55/100 | ⚠️ À améliorer | -| **Qualité du Code** | 60/100 | ⚠️ Intermédiaire | -| **Sécurité** | 50/100 | ⚠️ Critique | -| **RGPD** | 40/100 | 🚫 Non conforme | -| **SCORE GLOBAL** | **51/100** | ⚠️ **Prêt avec correctifs critiques** | - -### 🎯 Verdict Final - -**⚠️ PRÊT AVEC CORRECTIFS CRITIQUES** - -Le projet nécessite des correctifs importants avant la mise en production, notamment sur la sécurité et la conformité RGPD. - ---- - -## 1️⃣ PERFORMANCE & OPTIMISATION - -### ✅ Points Forts - -1. **Next.js 16.1.1** - Version récente avec App Router -2. **next/font** - Utilisation correcte de `Inter` avec `next/font/google` -3. **Dynamic imports** - Utilisation de `dynamic()` et `import()` pour le code splitting - - Exemple : `components/observatory/observatory-map.tsx` utilise `dynamic()` pour Leaflet - - Plusieurs imports dynamiques dans les services (caldav-sync, microsoft-calendar-sync) -4. **Redis caching** - Système de cache Redis implémenté -5. **Health check endpoint** - `/api/health` pour monitoring - -### 🚨 Problèmes Détectés - -#### 1. **Images non optimisées** ⚠️ CRITIQUE -```javascript -// next.config.mjs ligne 9-11 -images: { - unoptimized: true, // ❌ DÉSACTIVE l'optimisation Next.js -} -``` -**Impact :** -- Pas de lazy loading automatique -- Pas de conversion WebP/AVIF -- Pas de responsive images -- Augmentation du poids des pages - -**Exemples dans le code :** -- `app/missions/page.tsx` ligne 238 : `` au lieu de `` -- `app/mission-tab/[missionId]/page.tsx` ligne 222 : `` natif -- Seul `components/podcast.tsx` utilise `next/image` correctement - -#### 2. **Page principale en Client Component** ⚠️ IMPORTANT -```typescript -// app/page.tsx ligne 1 -"use client"; // ❌ Toute la page est client-side -``` -**Impact :** -- Pas de SSR pour la page d'accueil -- Hydration complète côté client -- Pas de streaming -- TTFB plus élevé - -#### 3. **Pas de metadata dans le layout principal** ⚠️ IMPORTANT -```typescript -// app/layout.tsx -// ❌ Pas de metadata exportée -``` -**Impact :** -- Pas de SEO de base -- Pas d'Open Graph -- Pas de description - -#### 4. **Utilisation excessive de localStorage/sessionStorage** ⚠️ MOYEN -- 72 occurrences de `localStorage`/`sessionStorage` -- Stockage de données utilisateur sans consentement explicite -- Risque RGPD (voir section 3) - -#### 5. **Pas de Suspense boundaries** ⚠️ MOYEN -- Aucun fichier `loading.tsx` trouvé -- Pas de gestion de loading states avec Suspense -- Spinners manuels dans les composants - -#### 6. **Pas de error.tsx** ⚠️ MOYEN -- Aucun fichier `error.tsx` trouvé -- Pas de gestion d'erreurs au niveau des routes -- Gestion d'erreurs uniquement dans les composants - -#### 7. **Bundle size non optimisé** ⚠️ MOYEN -- Beaucoup de dépendances lourdes chargées -- Pas de tree-shaking visible -- Pas d'analyse de bundle size - -### 📋 Recommandations Actionnables - -#### 🔴 CRITIQUE - Activer l'optimisation d'images - -```typescript -// next.config.mjs -const nextConfig = { - images: { - unoptimized: false, // ✅ Activer - formats: ['image/avif', 'image/webp'], - deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], - imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], - remotePatterns: [ - { - protocol: 'https', - hostname: '**', - }, - ], - }, -}; -``` - -Remplacer tous les `` par `` : -```typescript -// Avant -{mission.name} - -// Après -import Image from 'next/image'; -{mission.name} -``` - -#### 🟡 IMPORTANT - Convertir la page principale en Server Component - -```typescript -// app/page.tsx - Nouvelle version -import { getServerSession } from "next-auth/next"; -import { authOptions } from "@/app/api/auth/options"; -import { QuoteCard } from "@/components/quote-card"; -import { Calendar } from "@/components/calendar"; -import { News } from "@/components/news"; -import { Duties } from "@/components/flow"; -import { Email } from "@/components/email"; -import { Parole } from "@/components/parole"; -import { Suspense } from "react"; - -export default async function Home() { - const session = await getServerSession(authOptions); - - if (!session) { - redirect("/signin"); - } - - return ( -
-
-
- }> - - - }> - - - }> - - - }> - - -
-
- }> - - - }> - - -
-
-
- ); -} -``` - -#### 🟡 IMPORTANT - Ajouter metadata au layout - -```typescript -// app/layout.tsx -import type { Metadata } from "next"; - -export const metadata: Metadata = { - title: { - default: "NEAH - Plateforme de gestion", - template: "%s | NEAH" - }, - description: "Plateforme de gestion NEAH", - keywords: ["NEAH", "gestion", "missions"], - authors: [{ name: "NEAH Team" }], - openGraph: { - type: "website", - locale: "fr_FR", - url: process.env.NEXTAUTH_URL, - siteName: "NEAH", - title: "NEAH - Plateforme de gestion", - description: "Plateforme de gestion NEAH", - }, - robots: { - index: true, - follow: true, - }, -}; -``` - -#### 🟡 IMPORTANT - Créer loading.tsx et error.tsx - -```typescript -// app/loading.tsx -export default function Loading() { - return ( -
-
-
- ); -} -``` - -```typescript -// app/error.tsx -'use client'; - -import { useEffect } from 'react'; - -export default function Error({ - error, - reset, -}: { - error: Error & { digest?: string }; - reset: () => void; -}) { - useEffect(() => { - console.error(error); - }, [error]); - - return ( -
-

Une erreur est survenue

- -
- ); -} -``` - -#### 🟢 MOYEN - Optimiser le bundle size - -```bash -# Ajouter à package.json -"analyze": "ANALYZE=true next build" -``` - -Installer `@next/bundle-analyzer` : -```bash -npm install --save-dev @next/bundle-analyzer -``` - -```typescript -// next.config.mjs -const withBundleAnalyzer = require('@next/bundle-analyzer')({ - enabled: process.env.ANALYZE === 'true', -}); - -module.exports = withBundleAnalyzer(nextConfig); -``` - ---- - -## 2️⃣ BONNES PRATIQUES NEXT.JS & CODE QUALITY - -### ✅ Points Forts - -1. **Structure du projet** - Organisation claire avec `app/`, `components/`, `lib/` -2. **TypeScript** - Utilisation de TypeScript avec configuration stricte -3. **Séparation des responsabilités** - Services séparés (`lib/services/`) -4. **Validation d'environnement** - Script `validate-env.ts` présent -5. **Logger centralisé** - `lib/logger.ts` avec niveaux de log -6. **Gestion d'erreurs API** - Certaines routes ont une bonne gestion d'erreurs -7. **Health check** - Endpoint `/api/health` pour monitoring - -### 🚨 Problèmes Détectés - -#### 1. **ESLint et TypeScript désactivés en build** 🚨 CRITIQUE -```javascript -// next.config.mjs ligne 3-8 -eslint: { - ignoreDuringBuilds: true, // ❌ DANGEREUX -}, -typescript: { - ignoreBuildErrors: true, // ❌ DANGEREUX -}, -``` -**Impact :** -- Erreurs TypeScript ignorées -- Erreurs ESLint ignorées -- Risque de bugs en production - -#### 2. **Pas de tests** 🚨 CRITIQUE -- Aucun fichier `.test.ts` ou `.spec.ts` trouvé -- Pas de tests unitaires -- Pas de tests e2e -- Pas de coverage - -#### 3. **Pas de metadata SEO** ⚠️ IMPORTANT -- Metadata manquante dans la plupart des pages -- Pas de sitemap -- Pas de robots.txt -- Pas d'Open Graph complet - -#### 4. **Gestion d'erreurs incomplète** ⚠️ IMPORTANT -- Pas de `error.tsx` au niveau des routes -- Pas de `not-found.tsx` global -- Gestion d'erreurs incohérente dans les API routes - -#### 5. **Accessibilité (a11y) non vérifiée** ⚠️ MOYEN -- Pas de vérification d'accessibilité visible -- Pas d'attributs ARIA -- Contraste des couleurs non vérifié - -#### 6. **Console.log en production** ⚠️ MOYEN -- Beaucoup de `console.log` dans le code -- Logger configuré mais pas utilisé partout -- Risque de fuite d'informations - -#### 7. **Pas de rate limiting** ⚠️ MOYEN -- Pas de protection contre les abus -- API routes exposées sans limitation - -### 📋 Recommandations Actionnables - -#### 🔴 CRITIQUE - Réactiver ESLint et TypeScript - -```typescript -// next.config.mjs -const nextConfig = { - eslint: { - ignoreDuringBuilds: false, // ✅ Réactiver - dirs: ['app', 'components', 'lib'], // Limiter aux dossiers pertinents - }, - typescript: { - ignoreBuildErrors: false, // ✅ Réactiver - }, -}; -``` - -**Action immédiate :** Corriger toutes les erreurs TypeScript et ESLint avant de réactiver. - -#### 🔴 CRITIQUE - Ajouter des tests - -```bash -# Installer les dépendances de test -npm install --save-dev @testing-library/react @testing-library/jest-dom jest jest-environment-jsdom @types/jest -``` - -```json -// package.json -{ - "scripts": { - "test": "jest", - "test:watch": "jest --watch", - "test:coverage": "jest --coverage" - } -} -``` - -```typescript -// jest.config.js -const nextJest = require('next/jest') - -const createJestConfig = nextJest({ - dir: './', -}) - -const customJestConfig = { - setupFilesAfterEnv: ['/jest.setup.js'], - testEnvironment: 'jest-environment-jsdom', - moduleNameMapper: { - '^@/(.*)$': '/$1', - }, -} - -module.exports = createJestConfig(customJestConfig) -``` - -Exemple de test : -```typescript -// __tests__/components/quote-card.test.tsx -import { render, screen } from '@testing-library/react'; -import { QuoteCard } from '@/components/quote-card'; - -describe('QuoteCard', () => { - it('renders without crashing', () => { - render(); - expect(screen.getByRole('article')).toBeInTheDocument(); - }); -}); -``` - -#### 🟡 IMPORTANT - Créer sitemap et robots.txt - -```typescript -// app/sitemap.ts -import { MetadataRoute } from 'next'; - -export default function sitemap(): MetadataRoute.Sitemap { - const baseUrl = process.env.NEXTAUTH_URL || 'https://example.com'; - - return [ - { - url: baseUrl, - lastModified: new Date(), - changeFrequency: 'daily', - priority: 1, - }, - { - url: `${baseUrl}/missions`, - lastModified: new Date(), - changeFrequency: 'weekly', - priority: 0.8, - }, - // ... autres routes - ]; -} -``` - -```typescript -// app/robots.ts -import { MetadataRoute } from 'next'; - -export default function robots(): MetadataRoute.Robots { - return { - rules: { - userAgent: '*', - allow: '/', - disallow: ['/api/', '/signin', '/signout'], - }, - sitemap: `${process.env.NEXTAUTH_URL}/sitemap.xml`, - }; -} -``` - -#### 🟡 IMPORTANT - Créer not-found.tsx - -```typescript -// app/not-found.tsx -import Link from 'next/link'; - -export default function NotFound() { - return ( -
-

404

-

Page non trouvée

- - Retour à l'accueil - -
- ); -} -``` - -#### 🟡 MOYEN - Ajouter rate limiting - -```bash -npm install next-rate-limit -``` - -```typescript -// lib/rate-limit.ts -import { rateLimit } from 'next-rate-limit'; - -export const limiter = rateLimit({ - interval: 60 * 1000, // 1 minute - uniqueTokenPerInterval: 500, -}); -``` - -```typescript -// app/api/example/route.ts -import { limiter } from '@/lib/rate-limit'; - -export async function GET(request: Request) { - await limiter.check(10, 'CACHE_TOKEN'); // 10 requêtes par minute - // ... reste du code -} -``` - -#### 🟢 MOYEN - Améliorer l'accessibilité - -```typescript -// Exemple : Ajouter des attributs ARIA - -``` - -Installer un linter d'accessibilité : -```bash -npm install --save-dev eslint-plugin-jsx-a11y -``` - -### 📊 Niveau de Maturité - -**Niveau : Intermédiaire** ⚠️ - -**Justification :** -- ✅ Structure de projet solide -- ✅ TypeScript bien utilisé -- ❌ Pas de tests -- ❌ ESLint/TypeScript désactivés -- ⚠️ Gestion d'erreurs partielle -- ⚠️ SEO incomplet - ---- - -## 3️⃣ CONFORMITÉ RGPD (GDPR) - -### 🚨 Problèmes Détectés - -#### 1. **Stockage de données personnelles sans consentement** 🚨 CRITIQUE - -**localStorage/sessionStorage utilisé massivement :** -- 72 occurrences dans le code -- Stockage d'IDs utilisateur, tokens, données de session -- Pas de consentement explicite -- Pas de politique de rétention - -**Exemples problématiques :** -```typescript -// hooks/use-task-notifications.ts -localStorage.setItem('notified-task-ids', JSON.stringify(ids)); - -// hooks/use-calendar-event-notifications.ts -localStorage.setItem('notified-event-ids', JSON.stringify(ids)); - -// lib/cache-utils.ts -localStorage.setItem(fullKey, JSON.stringify(entry)); - -// app/page.tsx -sessionStorage.setItem('just_logged_out', 'true'); -``` - -#### 2. **Pas de politique de confidentialité visible** 🚨 CRITIQUE -- Aucune page `/privacy` ou `/confidentialite` trouvée -- Pas de mention légale -- Pas de politique de cookies - -#### 3. **Pas de gestion des droits utilisateurs** 🚨 CRITIQUE -- Pas d'endpoint pour accès aux données (Article 15) -- Pas d'endpoint pour rectification (Article 16) -- Pas d'endpoint pour suppression (Article 17 - droit à l'oubli) -- Pas d'export des données (Article 20) - -#### 4. **Cookies sans consentement** ⚠️ IMPORTANT -- Cookies Next-Auth utilisés (légitimes pour l'authentification) -- Mais pas de banner de consentement pour les cookies non essentiels -- Pas de distinction cookies essentiels / non essentiels - -#### 5. **Données partagées avec des tiers** ⚠️ IMPORTANT -- Keycloak (authentification) -- RocketChat (messages) -- Microsoft Graph (emails, calendrier) -- Leantime (tâches) -- Pas de mention explicite dans une politique de confidentialité - -#### 6. **Logs contenant potentiellement des données personnelles** ⚠️ MOYEN -```typescript -// lib/logger.ts -// Pas de sanitization des données avant logging -logger.debug('User data', { userId, email }); // Risque RGPD -``` - -#### 7. **Pas de minimisation des données** ⚠️ MOYEN -- Stockage de données non nécessaires -- Pas de nettoyage automatique des données obsolètes - -### 📋 Recommandations Actionnables - -#### 🔴 CRITIQUE - Créer une politique de confidentialité - -```typescript -// app/confidentialite/page.tsx -import { Metadata } from 'next'; - -export const metadata: Metadata = { - title: 'Politique de Confidentialité', -}; - -export default function ConfidentialitePage() { - return ( -
-

Politique de Confidentialité

- -
-

1. Collecte des données

-

Nous collectons les données suivantes :

-
    -
  • Données d'authentification (via Keycloak)
  • -
  • Emails et calendriers (via Microsoft Graph)
  • -
  • Messages (via RocketChat)
  • -
  • Tâches (via Leantime)
  • -
-
- -
-

2. Base légale

-

Le traitement est basé sur :

-
    -
  • Votre consentement
  • -
  • L'exécution d'un contrat
  • -
  • L'intérêt légitime
  • -
-
- -
-

3. Vos droits

-

Conformément au RGPD, vous disposez des droits suivants :

-
    -
  • Droit d'accès (Article 15)
  • -
  • Droit de rectification (Article 16)
  • -
  • Droit à l'effacement (Article 17)
  • -
  • Droit à la portabilité (Article 20)
  • -
  • Droit d'opposition (Article 21)
  • -
-
- -
-

4. Contact

-

Pour exercer vos droits, contactez : privacy@example.com

-
-
- ); -} -``` - -#### 🔴 CRITIQUE - Implémenter les droits utilisateurs - -```typescript -// app/api/gdpr/access/route.ts -import { NextResponse } from 'next/server'; -import { getServerSession } from 'next-auth'; -import { authOptions } from '@/app/api/auth/options'; -import { prisma } from '@/lib/prisma'; - -export async function GET() { - const session = await getServerSession(authOptions); - if (!session?.user?.id) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); - } - - // Collecter toutes les données de l'utilisateur - const userData = { - profile: await prisma.user.findUnique({ - where: { id: session.user.id }, - }), - emails: await prisma.email.findMany({ - where: { userId: session.user.id }, - }), - calendars: await prisma.calendar.findMany({ - where: { userId: session.user.id }, - }), - // ... autres données - }; - - return NextResponse.json(userData); -} -``` - -```typescript -// app/api/gdpr/delete/route.ts -export async function DELETE() { - const session = await getServerSession(authOptions); - if (!session?.user?.id) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); - } - - // Supprimer toutes les données de l'utilisateur - await prisma.user.delete({ - where: { id: session.user.id }, - }); - - // Nettoyer localStorage côté client - // (nécessite une action côté client) - - return NextResponse.json({ success: true }); -} -``` - -#### 🔴 CRITIQUE - Ajouter un banner de consentement cookies - -```typescript -// components/cookie-consent.tsx -'use client'; - -import { useState, useEffect } from 'react'; -import { Button } from '@/components/ui/button'; - -export function CookieConsent() { - const [showBanner, setShowBanner] = useState(false); - - useEffect(() => { - const consent = localStorage.getItem('cookie-consent'); - if (!consent) { - setShowBanner(true); - } - }, []); - - const acceptCookies = () => { - localStorage.setItem('cookie-consent', 'accepted'); - localStorage.setItem('cookie-consent-date', new Date().toISOString()); - setShowBanner(false); - }; - - const rejectCookies = () => { - localStorage.setItem('cookie-consent', 'rejected'); - // Supprimer les cookies non essentiels - // ... - setShowBanner(false); - }; - - if (!showBanner) return null; - - return ( -
-
-
-

- Nous utilisons des cookies pour améliorer votre expérience. - - En savoir plus - -

-
-
- - -
-
-
- ); -} -``` - -#### 🟡 IMPORTANT - Minimiser le stockage localStorage - -```typescript -// lib/storage-utils.ts -export class GDPRCompliantStorage { - private static getConsent(): boolean { - return localStorage.getItem('cookie-consent') === 'accepted'; - } - - static setItem(key: string, value: string): void { - if (!this.getConsent()) { - console.warn('Storage blocked: no consent'); - return; - } - - // Ajouter une date d'expiration - const entry = { - value, - expiresAt: Date.now() + (30 * 24 * 60 * 60 * 1000), // 30 jours - }; - - localStorage.setItem(key, JSON.stringify(entry)); - } - - static getItem(key: string): string | null { - if (!this.getConsent()) { - return null; - } - - const item = localStorage.getItem(key); - if (!item) return null; - - try { - const entry = JSON.parse(item); - if (entry.expiresAt && Date.now() > entry.expiresAt) { - localStorage.removeItem(key); - return null; - } - return entry.value; - } catch { - return item; // Fallback pour compatibilité - } - } - - static clearUserData(userId: string): void { - // Nettoyer toutes les données d'un utilisateur - const keys = Object.keys(localStorage); - keys.forEach(key => { - if (key.includes(userId) || key.startsWith('notified-')) { - localStorage.removeItem(key); - } - }); - } -} -``` - -#### 🟡 IMPORTANT - Sanitizer les logs - -```typescript -// lib/logger.ts - Amélioration -export const logger = { - // ... existing code ... - - sanitize(data: any): any { - if (!data || typeof data !== 'object') return data; - - const sensitive = ['password', 'token', 'secret', 'key', 'email']; - const sanitized = { ...data }; - - for (const key in sanitized) { - if (sensitive.some(s => key.toLowerCase().includes(s))) { - sanitized[key] = '[REDACTED]'; - } - } - - return sanitized; - }, - - debug(...args: any[]) { - if (!isProd) { - console.debug(...args.map(arg => - typeof arg === 'object' ? this.sanitize(arg) : arg - )); - } - }, -}; -``` - -### 📊 Niveau de Conformité - -**Niveau : Faible** 🚫 - -**Justification :** -- ❌ Pas de politique de confidentialité -- ❌ Pas de gestion des droits utilisateurs -- ❌ Stockage localStorage sans consentement -- ❌ Pas de banner cookies -- ⚠️ Données partagées avec tiers non documentées -- ⚠️ Logs non sanitizés - ---- - -## 4️⃣ SÉCURITÉ - -### ✅ Points Forts - -1. **Next-Auth** - Utilisation de Next-Auth avec Keycloak -2. **Cookies sécurisés** - Configuration correcte des cookies (httpOnly, sameSite) -3. **DOMPurify** - Utilisé pour sanitizer le HTML (emails) -4. **Validation d'environnement** - Script de validation des variables d'environnement -5. **Health check** - Endpoint de monitoring - -### 🚨 Problèmes Détectés - -#### 1. **Headers de sécurité incomplets** 🚨 CRITIQUE - -```javascript -// next.config.mjs ligne 20-31 -async headers() { - return [ - { - source: '/:path*', - headers: [ - { - key: 'Content-Security-Policy', - value: "frame-ancestors 'self' https://espace.slm-lab.net https://connect.slm-lab.net" - // ❌ CSP incomplet, manque beaucoup de directives - } - ] - } - ] -} -``` - -**Manque :** -- X-Frame-Options -- X-Content-Type-Options -- X-XSS-Protection -- Referrer-Policy -- Permissions-Policy -- Strict-Transport-Security (HSTS) - -#### 2. **CSP trop permissif** 🚨 CRITIQUE -- CSP ne couvre que `frame-ancestors` -- Pas de protection contre XSS -- Pas de restriction des sources de scripts/styles - -#### 3. **Variables d'environnement exposées** ⚠️ IMPORTANT -```typescript -// Beaucoup d'utilisation de process.env.NEXT_PUBLIC_* -// Ces variables sont exposées au client -``` -- Risque si des secrets sont dans `NEXT_PUBLIC_*` - -#### 4. **Pas de rate limiting** ⚠️ IMPORTANT -- API routes non protégées contre les abus -- Risque de DDoS -- Risque de brute force - -#### 5. **Gestion d'erreurs trop verbeuse** ⚠️ MOYEN -```typescript -// Certaines routes retournent des détails d'erreur -return NextResponse.json({ - error: "Failed", - details: errorMessage, // ❌ Peut exposer des infos sensibles -}); -``` - -#### 6. **Pas de CSRF protection explicite** ⚠️ MOYEN -- Next-Auth gère le CSRF pour l'auth -- Mais pas de protection explicite pour les autres endpoints - -#### 7. **Script inline dans le layout** ⚠️ MOYEN -```typescript -// app/layout.tsx ligne 29-36 -