# 06 — Sécurité et conformité RGPD ## 1. Analyse de risque (résumé) | Menace | Vecteur | Niveau (v1) | Contre-mesure | | --- | --- | --- | --- | | XSS — injection de HTML/JS saisi par l'utilisateur | champ Markdown rendu via `dangerouslySetInnerHTML` | **élevé** si non traité | **DOMPurify.sanitize()** systématique sur le HTML produit par `marked` | | Vol de données | exfiltration réseau | nul | **aucune donnée quitte le navigateur** (pas d'API, pas d'appel distant) | | Corruption de la sauvegarde | JSON invalide en localStorage | faible | parsing try/catch + validation de forme + valeur par défaut | | Quota localStorage dépassé | très gros CV | faible | erreur catchée + `console.warn` (enregistrement silencieux) | | Données lues par un tiers sur le poste | accès local au navigateur | hors périmètre | relatives au poste utilisateur (aucune garantie applicative possible) | Rappel : **le seul point d'entrée présentant un risque d'exécution** est le rendu HTML. Mitigé par la règle « aucun HTML brut n'est injecté, uniquement le résultat de `markdownToHtml` (marked → DOMPurify) ». ## 2. Chaîne de rendu sécurisée (obligatoire) ``` Markdown brut (textarea) │ marked.parse (GFM, breaks) ▼ HTML intermédiaire non sûr │ DOMPurify.sanitize(html, { USE_PROFILES: { html: true } }) ▼ HTML assaini │ dangerouslySetInnerHTML={{ __html: sanitizedHtml }} ▼ DOM ``` ### Règles d'implémentation 1. Toute injection dans le DOM passe **exclusivement** par `lib/markdown.ts` → `markdownToHtml`. 2. Ne jamais injecter la saisie brute (une `textarea` n'est pas un `` dans chaque zone → aucune exécution. - [ ] Page `/mentions-legales` présente et linker depuis le footer (masqué à l'impression).