5.7 KiB
5.7 KiB
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
- Toute injection dans le DOM passe exclusivement par
lib/markdown.ts→markdownToHtml. - Ne jamais injecter la saisie brute (une
textarean'est pas un<script>: le texte est du texte ; le risque n'apparaît que lors du rendu HTML). - Ne pas surcharger la config DOMPurify par zone ; une configuration unique module
06-est utilisée partout. markedoptions stables :gfm: true,breaks: true. Ne pas activer d'extension/plugin non maîtrisé.- Le rendu est déterministe (pas de rendu serveur du Markdown utilisateur pour les zones interactives — le client est le seul excécutant).
dompurifyest importé seulement dans les composants client (prérequiswindow), jamais dans un composant serveur/réseau.
Ce que DOMPurify bloque (défauts)
- balises
<script>,<iframe>,<object>,<embed>,<svg>non sûres ; - gestionnaires d'événements inline (
onclick=,onerror=) ; - URLs
javascript:danshref/src; - tout futur composant exotique inconnu.
3. Données personnelles : état de l'analyse
Les zones 1 à 6 du CV contiennent des données à caractère personnel (nom, e-mail, téléphone, histoire professionnelle).
| Propriété | État |
|---|---|
| Stockage | localStorage du navigateur, sur le poste seulement |
| Transmission | aucune (pas d'envoi réseau, pas de cookies, pas de tracker, pas d'analytics) |
| Durée de conservation | jusqu'à effacement des données du navigateur, ou « Réinitialiser le CV » dans l'application |
| Accès | celui qui possède le poste/navigateur |
| Base légale (contrôle qualité RGPD) | l'utilisateur est le seul responsable et destinataire ; aucune RGDP externe ne traite ces données |
Conclusion : l'application n'effectue aucun traitement débordant l'usage personnel de l'utilisateur. La page /mentions-legales doit le formuler clairement et fournir les droits usuels (accès, rectification, suppression — effectuables directement dans l'app/browser).
4. Contenu de la page /mentions-legales (modèle de rédaction)
Sections à inclure (v1 : sans paragraphe contact) :
- Titre — « Mentions légales ».
- Éditeur / responsable de traitement : l'utilisateur lui-même (pas d'entité tierce).
- Données traitées : les contenus saisis (état civil, contacts, parcours…).
- Finalité : production d'un CV local ; aucune transmission.
- Stockage : localStorage du navigateur (clé
cv-maker:v1), jamais envoyé à un serveur. - Durée de conservation : tant que les données du navigateur existent ; possibilité de suppression immédiate.
- Droits de la personne concernée : libre disposition des données — modification/suppression dans l'éditeur ; effacement possible via les outils du navigateur (suggestion d'actions concrètes) ou le bouton « Réinitialiser ».
- Sécurité : rendu assaini (aucune exécution de contenu saisi), aucune dépendance réseau.
- Contact : section retirée en v1 (cf. demande utilisateur).
- Date de mise à jour de la page.
5. Sécurité applicative transversale
- PWA/service worker : le SW ne précache que des routes statiques internes ; aucun champ utilisateur n'y est inscrit (les données restent dans localStorage, hors périmètre du cache de pages).
- Dépendances : audit régulier
pnpm audit; mise à jour demarked/dompurify(les deux librairies de sécurité critiques). - Headers de réponse (side) : valeurs par défaut convenables pour Next.js de production ; pas d'en-tête supplémentaire requis côté local (pas de cookies).
- Content-Security-Policy (recommandation) : à documenter comme évolution — les pages statiques ne chargent aucun script tiers, une CSP stricte est triviale à ajouter hors v1 si hébergé.
6. Checklist sécurité avant livraison
- Toute zone rendue passe par
markdownToHtml(relire chaquedangerouslySetInnerHTML). - Aucun appel réseau dans le code applicatif (grep
fetch(,axios,XMLHttpRequestdansapp/etcomponents/). pnpm auditsans vulnérabilité de haut niveau.- Test manuel d'injection : saisir
<img src=x onerror=alert(1)>et<script>alert(1)</script>dans chaque zone → aucune exécution. - Page
/mentions-legalesprésente et linker depuis le footer (masqué à l'impression).