Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

🧬 Cross-Site Scripting XSS — Guide HTML IDEO-Lab

Guide interactif, didactique et opérationnel : modèle mental, familles XSS, contextes d’encodage, exemples sûrs, CSP, Trusted Types, frameworks, tests, incident response et checklist finale.

Positionnement : le XSS n’est pas une simple erreur de formulaire. C’est une rupture de frontière entre donnée et code dans le navigateur. Le guide privilégie les exemples défensifs, les canaris neutralisés et les corrections professionnelles.
Cadre pédagogique : les extraits servent à comprendre les anti-patterns et les corrections. Les scénarios de vol de session, contournement WAF ou exploitation active ne sont pas détaillés ; l’accent reste mis sur la prévention, la détection et la remédiation.
3 famillesReflected, Stored, DOM-based.
5 contextesHTML, attribut, JavaScript, CSS, URL.
4 défensesEncode, sanitize, CSP, tests.
1 réflexeDonnée ≠ code.
01

🧠 Vue d’ensemble XSS

Comprendre l’injection de script côté navigateur

FondamentauxNavigateurRisque métier
02

🧩 Modèle mental du navigateur

Pourquoi le contexte change tout

HTML parserDOMContextes
03

🧬 Familles de XSS

Reflected, Stored, DOM-based, mutation et blind XSS

TypologieStoredDOM
04

🎯 Règle des contextes

HTML, attribut, JavaScript, CSS et URL

EncodageContexteOWASP
05

💾 XSS stocké

Le risque persistant dans les contenus, profils et back-offices

StoredBase de donnéesBack-office
06

🪞 XSS réfléchi

Paramètres, recherche et messages immédiats

ReflectedQuery stringErreur
07

🌐 DOM XSS

Sources, sinks et frameworks front-end

DOMFront-endJavaScript
08

🔐 Encodage de sortie

La défense numéro un contre le XSS classique

Output encodingEscapingTemplates
09

🧼 Sanitization HTML

Quand le HTML riche est vraiment nécessaire

DOMPurifyAllowlistWYSIWYG
10

🛡️ CSP et Trusted Types

Réduire l’impact et verrouiller les sinks modernes

CSPNonceTrusted Types
11

🍪 Sessions, cookies et impact

Limiter les dégâts quand une faille existe

HttpOnlySameSiteSession
12

🏗️ Frameworks modernes

Django, React, Vue, Angular et composants tiers

DjangoReactTemplates
13

🔎 Détection et tests

SAST, DAST, revue manuelle et tests navigateur

SASTDASTQA
14

🚧 WAF / WAAP et limites

Filtrer ne remplace pas corriger

WAFWAAPDefense in depth
15

🚨 Réponse à incident XSS

Contenir, enquêter, corriger et communiquer

IncidentSOCForensics
16

🎮 Mini-lab pédagogique

Apprendre sans mettre en danger

LudiqueLabDidactique
17

🏰 Architecture anti-XSS

Contrôles empilés du code au navigateur

ArchitectureSecure by designSDLC
18

📌 Cheat-sheet finale

Décisions rapides, checklist et références

SynthèseChecklistRéférences
01. Vue d’ensemble XSS — Comprendre l’injection de script côté navigateur
Vue d’ensemble XSS

Le Cross-Site Scripting correspond à une injection de contenu interprété par le navigateur comme du code actif. Le cœur du problème n’est pas seulement l’entrée utilisateur, mais le moment où une donnée non fiable franchit une frontière de contexte : HTML, attribut, URL, JavaScript, CSS ou DOM. La défense repose sur un principe simple et exigeant : aucune donnée non fiable ne doit atteindre un contexte exécutable sans encodage, validation, sanitation ou isolation adaptés.

FondamentauxNavigateurRisque métier
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Vue d’ensemble XSSSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Un navigateur n’exécute pas une page comme un texte linéaire. Il parse successivement du HTML, des attributs, des URL, du CSS, du JavaScript et des événements DOM. Une même chaîne peut être inoffensive dans un texte HTML, dangereuse dans un attribut, catastrophique dans une chaîne JavaScript et ambiguë dans une URL. La sécurité XSS est donc une sécurité de contexte, pas une simple recherche de caractères interdits.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Mini-scène pédagogique
Anti-pattern
Recherche affichée directement : <p>Résultat pour : {{ q|safe }}</p>
La donnée q peut devenir une partie de la page plutôt qu’un simple texte.
Correction attendue
Recherche affichée comme texte : <p>Résultat pour : {{ q }}</p>
Le moteur de template encode la donnée dans le contexte HTML attendu.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Modèle de défense principal : auto-escaping par défaut, encodage contextuel, refus des HTML arbitraires, sanitation contrôlée lorsque du HTML riche est réellement nécessaire, CSP stricte, cookies HttpOnly/Secure/SameSite et revue des points d’injection DOM.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
RisqueLa page exécute du code non prévu dans la session de la victime.
ImpactVol de session, actions frauduleuses, défiguration, pivot interne, fraude métier.
Contrôle cléTraiter toute donnée externe comme non fiable jusqu’à sa sortie contrôlée.
Erreur classiqueValider en entrée puis oublier l’encodage de sortie.
Checklist
  • Cartographier les zones où les données utilisateur sont réaffichées.
  • Identifier les contextes de sortie : HTML, attribut, JS, URL, CSS, DOM.
  • Interdire les contournements de template du type safe/raw sans justification.
  • Prévoir un test XSS dans chaque revue de fonctionnalité exposée.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
02. Modèle mental du navigateur — Pourquoi le contexte change tout
Modèle mental du navigateur

Le navigateur est une machine à interpréter plusieurs langages imbriqués. Il construit le DOM à partir du HTML, applique des attributs et styles, charge des ressources, puis exécute des scripts qui peuvent relire et modifier la page. Le XSS apparaît lorsqu’une donnée prévue comme texte devient balise, attribut, URL, gestionnaire d’événement, fragment JavaScript ou entrée d’un sink DOM dangereux.

HTML parserDOMContextes
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Modèle mental du navigateurSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

La même valeur traverse souvent plusieurs couches : requête HTTP, serveur, template, JSON, JavaScript client, DOM. Chaque changement de couche peut créer un nouveau contexte. Une donnée encodée correctement pour du HTML peut devenir dangereuse si elle est ensuite réutilisée dans un script ou injectée via innerHTML. Les failles modernes viennent souvent de ces réutilisations invisibles.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Chaîne de confiance simplifiée
Anti-pattern
const name = new URLSearchParams(location.search).get("name");
document.querySelector("#hello").innerHTML = name; // anti-pattern pédagogique
Correction attendue
const name = new URLSearchParams(location.search).get("name");
document.querySelector("#hello").textContent = name; // texte, pas HTML
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Séparer strictement les intentions : textContent pour du texte, setAttribute seulement avec valeurs validées, URL construites par API, HTML riche uniquement après sanitation, interdiction de document.write, eval, Function, innerHTML non contrôlé et insertAdjacentHTML non filtré.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
SourceURL, fragment, postMessage, localStorage, API, WebSocket, cookie accessible JS.
SinkinnerHTML, outerHTML, document.write, insertAdjacentHTML, srcdoc, eval, setTimeout string.
FrontièreMoment où une donnée devient interprétable par le navigateur.
Bonne pratiqueChoisir une API sûre plutôt que filtrer après coup.
Checklist
  • Lister les sources de données côté client.
  • Lister les sinks DOM dangereux.
  • Remplacer innerHTML par textContent lorsque du HTML n’est pas requis.
  • Ajouter des tests unitaires sur les composants qui rendent du contenu externe.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
03. Familles de XSS — Reflected, Stored, DOM-based, mutation et blind XSS
Familles de XSS

Les catégories historiques restent utiles : XSS réfléchi lorsque la donnée revient immédiatement dans la réponse, XSS stocké lorsqu’elle persiste en base ou dans un système intermédiaire, DOM XSS lorsque le client transforme une donnée non fiable en code. Des variantes existent : mutation XSS, blind XSS dans des back-offices, XSS via Markdown, SVG, PDF viewer, templates client ou widgets tiers.

TypologieStoredDOM
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Familles de XSSSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Le reflected XSS touche souvent les paramètres de recherche, messages d’erreur ou redirections. Le stored XSS vise commentaires, profils, tickets, noms de fichiers, logs visibles, champs CMS. Le DOM XSS naît dans les scripts front-end : une source comme location.hash ou postMessage alimente un sink comme innerHTML. Le blind XSS se déclenche plus tard, dans une console admin ou un outil support.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Cartographie rapide
Anti-pattern
Champ commentaire enregistré puis rendu avec un filtre raw/safe dans le back-office.
Correction attendue
Champ commentaire rendu comme texte, ou HTML autorisé passé dans un sanitizer avec allowlist stricte.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

La priorité est plus élevée pour le XSS stocké et blind, car l’exploitation peut toucher des comptes internes privilégiés. Les flux support, CRM, admin, ticketing, logs et observabilité doivent être traités comme des surfaces de rendu à part entière.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
ReflectedRequête → réponse immédiate. Testable sur paramètres et messages.
StoredDonnée persistée → affichage futur. Impact souvent plus fort.
DOM-basedSource client → sink client. Ne se voit pas toujours dans la réponse serveur.
BlindDéclenchement différé dans un outil interne ou back-office.
Checklist
  • Classer chaque finding XSS par famille.
  • Prioriser stored/blind/admin.
  • Tester les zones d’administration, pas seulement le front public.
  • Inclure les champs peu visibles : nom fichier, libellé, tag, user-agent, logs.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
04. Règle des contextes — HTML, attribut, JavaScript, CSS et URL
Règle des contextes

La prévention XSS repose sur une règle centrale : l’encodage doit correspondre au contexte exact de sortie. Un encodage HTML ne protège pas nécessairement une chaîne JavaScript. Un encodage URL ne protège pas un attribut événementiel. Un attribut HTML sans guillemets est plus difficile à sécuriser. Le contexte détermine la défense, pas le nom du champ ni sa provenance.

EncodageContexteOWASP
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Règle des contextesSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Les parseurs changent de mode selon les caractères rencontrés. Dans le corps HTML, les caractères critiques sont notamment <, >, &, guillemets selon le contexte. Dans un attribut, les guillemets et espaces modifient la structure. Dans JavaScript, les quotes, backticks, antislashs, fins de ligne et séquences Unicode ont une autre signification. Dans CSS et URL, d’autres règles s’appliquent. Une solution générique unique est donc insuffisante.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Table de décision
Anti-pattern
<a href="{{ user_url }}">Profil</a> sans validation de schéma ni encodage adapté.
Correction attendue
Valider le schéma http/https, normaliser l’URL, encoder l’attribut, refuser javascript:, data: et schémas inattendus.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Appliquer la matrice OWASP : HTML encode pour le texte, attribute encode pour les attributs, JavaScript encode pour les chaînes JS, URL encode pour les paramètres, CSS encode si un contexte CSS est absolument nécessaire. Éviter les contextes dangereux quand une API sûre existe.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
HTML bodyÉchapper les caractères qui créent des balises ou entités.
Attribut HTMLToujours mettre les valeurs entre guillemets et encoder l’attribut.
JavaScript stringPréférer JSON sérialisé et escape JS contextuel.
URLValider schéma/hôte puis encoder les paramètres.
CSSÉviter les valeurs dynamiques ; utiliser allowlist stricte.
Checklist
  • Identifier le contexte de chaque interpolation.
  • Supprimer les attributs événementiels dynamiques.
  • Éviter les templates JS inline avec variables non sérialisées.
  • Ajouter une revue dédiée aux href, src, srcdoc, style et data-* exploités par JS.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
05. XSS stocké — Le risque persistant dans les contenus, profils et back-offices
XSS stocké

Le XSS stocké est particulièrement dangereux, car la charge est persistée puis servie à plusieurs utilisateurs, parfois à des administrateurs. Les zones classiques sont commentaires, biographies, noms de projet, champs CRM, tickets support, logs applicatifs, noms de fichiers, notifications, messages internes et contenu CMS.

StoredBase de donnéesBack-office
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
XSS stockéSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

La donnée peut être proprement validée à l’entrée, puis devenir dangereuse à la sortie si elle est rendue dans le mauvais contexte. Un nom de fichier affiché dans un tableau admin, un user-agent dans un viewer de logs ou le titre d’un ticket dans une notification HTML peuvent devenir des points d’exécution. Le XSS stocké se nourrit des interfaces secondaires que personne ne considère comme publiques.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Ticket support
Anti-pattern
Titre ticket enregistré : contenu utilisateur rendu en HTML dans une console support avec |safe.
Correction attendue
Titre ticket rendu comme texte ; description riche sanitizée côté serveur ; aperçu admin soumis aux mêmes règles que le front.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Contrôler les rendus back-office avec la même rigueur que les pages publiques. Séparer texte simple et HTML riche. Mettre en place une sanitation allowlist pour les éditeurs WYSIWYG, journaliser les nettoyages et conserver une version brute non affichée uniquement si nécessaire.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
Signal faibleUne donnée “interne” est affichée sans escaping.
ImpactCompromission d’un compte support/admin ou action en masse.
TestCréer du contenu neutralisé et vérifier le rendu dans toutes les vues.
MesureAucun rendu safe/raw sans justification de sécurité.
Checklist
  • Auditer admin, support, CRM, reporting, exports HTML.
  • Traiter logs et user-agent comme entrées hostiles.
  • Désactiver HTML riche si non nécessaire.
  • Ajouter une validation sécurité aux composants de rendu communs.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
06. XSS réfléchi — Paramètres, recherche et messages immédiats
XSS réfléchi

Le XSS réfléchi survient lorsqu’une donnée fournie dans une requête HTTP est intégrée immédiatement dans la réponse de manière non sûre. Il concerne souvent les pages de recherche, filtres, messages d’erreur, paramètres de redirection, pages de statut, formulaires et bannières de confirmation.

ReflectedQuery stringErreur
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
XSS réfléchiSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

L’exploitation dépend fréquemment d’un lien transmis à une victime. Le risque réel dépend du contexte d’exécution, des cookies, des droits de la victime, de la CSP et des protections de session. Même lorsqu’il n’y a pas de persistance, l’impact peut être élevé si la victime est authentifiée ou si la page contient des données sensibles.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Recherche
Anti-pattern
<p>Recherche : {{ request.GET.q|safe }}</p>
Correction attendue
<p>Recherche : {{ request.GET.q }}</p> avec auto-escape et aucun HTML attendu.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Ne jamais utiliser de filtre raw/safe pour un paramètre de requête. Définir un composant d’affichage des messages qui encode systématiquement. Tester les paramètres q, search, next, redirect, error, msg, tab, returnUrl et fragment exploité côté client.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
SurfaceParamètres GET/POST et messages instantanés.
SymptômeLa valeur saisie apparaît dans la page.
ContrôleEncodage contextuel au rendu.
RenfortCSP avec nonce et cookies HttpOnly/SameSite.
Checklist
  • Tester les paramètres visibles dans l’HTML.
  • Vérifier les pages d’erreur personnalisées.
  • Refuser les redirections ouvertes dangereuses.
  • Contrôler les bannières flash/messages système.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
07. DOM XSS — Sources, sinks et frameworks front-end
DOM XSS

Le DOM XSS se produit côté client lorsque du JavaScript lit une donnée non fiable puis l’insère dans un sink capable d’interpréter du HTML, du script ou une URL active. Les frameworks modernes réduisent certaines erreurs, mais les réintroduisent via HTML brut, composants tiers, templates client, Markdown, routeurs, postMessage ou manipulation directe du DOM.

DOMFront-endJavaScript
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
DOM XSSSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Une page peut sembler sûre côté serveur : aucune charge dangereuse n’apparaît dans la réponse initiale. Pourtant, le code client peut lire location.hash, localStorage, postMessage ou une réponse API et construire ensuite du HTML. Les scans purement serveur ratent souvent cette classe ; il faut analyser le flux source → sink dans le JavaScript exécuté.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Source → sink
Anti-pattern
const html = location.hash.slice(1);
preview.innerHTML = html;
Correction attendue
const text = location.hash.slice(1);
preview.textContent = text;
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Remplacer les sinks dangereux par des API textuelles. Pour le HTML riche, centraliser un sanitizer robuste, imposer Trusted Types quand possible, interdire les manipulations DOM brutes hors composants approuvés et surveiller les dépendances front-end.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
Sourceslocation, hash, search, postMessage, localStorage, API, WebSocket.
SinksinnerHTML, outerHTML, insertAdjacentHTML, document.write, srcdoc.
DétectionTaint analysis, revue JS, tests dynamiques navigateur.
ContrôletextContent, DOM APIs sûres, sanitizer, Trusted Types.
Checklist
  • Chercher innerHTML et insertAdjacentHTML dans le dépôt.
  • Contrôler les handlers postMessage et origines autorisées.
  • Encadrer les composants Markdown/WYSIWYG.
  • Activer un mode CSP report-only pour repérer les scripts inline.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
08. Encodage de sortie — La défense numéro un contre le XSS classique
Encodage de sortie

L’encodage de sortie transforme une donnée non fiable en représentation textuelle sûre dans un contexte donné. Il ne supprime pas la donnée ; il empêche le navigateur de l’interpréter comme structure ou code. C’est la défense fondamentale pour les contenus simples : noms, titres, commentaires texte, résultats de recherche, labels, messages et valeurs affichées.

Output encodingEscapingTemplates
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Encodage de sortieSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

L’encodage doit se produire le plus près possible de la sortie, car le contexte final est connu à cet endroit. Encoder trop tôt peut provoquer des doubles encodages ou donner une fausse impression de sécurité. La validation d’entrée reste utile pour la qualité métier, mais ne remplace pas l’encodage de sortie.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Django template
Anti-pattern
{{ comment.body|safe }}  {# dangereux si comment.body vient d’un utilisateur #}
Correction attendue
{{ comment.body }}  {# auto-escape HTML par défaut #}
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Utiliser les mécanismes natifs du framework. Interdire les sorties raw/safe par défaut. Prévoir des helpers spécifiques par contexte. Les données destinées à JavaScript doivent être sérialisées en JSON sûr, pas concaténées dans un script inline.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
HTML texteAuto-escape du moteur de template.
AttributGuillemets + escape attribut.
JSSérialisation JSON ou escapejs contextuel.
URL paramConstruction par API URLSearchParams.
HTML richeSanitizer, pas simple escaping.
Checklist
  • Rechercher safe, raw, mark_safe, dangerouslySetInnerHTML.
  • Documenter chaque exception.
  • Créer un helper unique pour JSON dans script.
  • Tester les caractères < > & " '.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
09. Sanitization HTML — Quand le HTML riche est vraiment nécessaire
Sanitization HTML

La sanitation consiste à accepter du HTML contrôlé tout en retirant les balises, attributs et protocoles dangereux. Elle est nécessaire pour commentaires riches, éditeurs WYSIWYG, contenus CMS, documentation, Markdown converti en HTML ou imports externes. Elle doit être basée sur une allowlist explicite, pas sur une blacklist fragile.

DOMPurifyAllowlistWYSIWYG
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Sanitization HTMLSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Un sanitizer robuste comprend les subtilités de parsing HTML/SVG/MathML, les attributs événementiels, URL dangereuses, namespaces, mutations DOM et cas limites navigateur. Une regex maison est insuffisante. La sanitation doit être appliquée avant l’insertion dans le DOM et configurée selon le besoin exact : tags autorisés, attributs autorisés, protocoles autorisés, liens rel=noopener, images éventuellement proxyfiées.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
HTML riche contrôlé
Anti-pattern
preview.innerHTML = markdownToHtml(userMarkdown); // sans sanitation
Correction attendue
const dirty = markdownToHtml(userMarkdown);
const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });
preview.innerHTML = clean;
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Centraliser la sanitation, figer une configuration, tester les régressions, surveiller les mises à jour du sanitizer, éviter les profils trop permissifs et ne jamais réactiver les attributs événementiels. Le HTML riche doit rester une exception métier.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
AllowlistBalises et attributs explicitement autorisés.
Protocoleshttp/https/mailto selon besoin ; refuser javascript/data sauf cas strict.
MarkdownConvertir puis sanitiser le HTML produit.
StockageStocker brut + rendu nettoyé selon politique, ou nettoyer à la sortie.
Checklist
  • Justifier le besoin de HTML riche.
  • Utiliser un sanitizer maintenu.
  • Tester SVG, liens, images, tableaux et attributs data.
  • Interdire la configuration locale dispersée.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
10. CSP et Trusted Types — Réduire l’impact et verrouiller les sinks modernes
CSP et Trusted Types

Content Security Policy n’est pas une excuse pour oublier l’encodage, mais un filet de sécurité très précieux. Une CSP stricte réduit l’exécution de scripts non autorisés, limite les sources de ressources, bloque certains comportements dangereux et fournit des rapports. Trusted Types ajoute un verrou côté navigateur sur les sinks DOM sensibles.

CSPNonceTrusted Types
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
CSP et Trusted TypesSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Une CSP efficace évite 'unsafe-inline', utilise des nonces ou hashes pour les scripts autorisés, définit object-src 'none', base-uri 'self', frame-ancestors, connect-src et img-src selon le besoin. Trusted Types force certains sinks à recevoir des objets TrustedHTML/TrustedScript créés par des politiques explicites, ce qui rend les erreurs innerHTML beaucoup plus visibles.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Politique de départ
Anti-pattern
Content-Security-Policy: script-src * 'unsafe-inline' 'unsafe-eval'
Correction attendue
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{RANDOM}'; object-src 'none'; base-uri 'self'; require-trusted-types-for 'script'; trusted-types app-sanitizer;
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Déployer en report-only, corriger les violations, puis passer en enforcement. Les nonces doivent être uniques par réponse. Les bibliothèques tierces doivent être inventoriées. La CSP doit être testée automatiquement afin d’éviter les assouplissements accidentels.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
script-srcSources de scripts et nonces/hashes.
object-srcnone dans la majorité des applications modernes.
base-uriself pour éviter les détournements de résolution.
report-uri/report-toCollecte des violations CSP.
Trusted TypesContrôle type-level des sinks DOM.
Checklist
  • Commencer par report-only.
  • Supprimer les scripts inline non nécessaires.
  • Mettre en place nonces côté serveur.
  • Collecter et analyser les rapports CSP.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
11. Sessions, cookies et impact — Limiter les dégâts quand une faille existe
Sessions, cookies et impact

Une faille XSS s’exécute dans le navigateur de la victime. Les cookies, tokens, données du DOM, actions applicatives et API accessibles par la session sont donc exposés. Les flags HttpOnly, Secure et SameSite ne corrigent pas le XSS, mais ils réduisent certains impacts, notamment le vol direct de cookie par JavaScript.

HttpOnlySameSiteSession
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Sessions, cookies et impactSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

HttpOnly empêche JavaScript de lire un cookie, mais n’empêche pas une action authentifiée depuis la page compromise. SameSite réduit certaines attaques intersites, Secure impose HTTPS, et une rotation de session limite la durée d’exploitation. Les tokens stockés dans localStorage restent accessibles au JavaScript injecté et constituent donc un risque important.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Cookie de session durci
Anti-pattern
Set-Cookie: sessionid=abc123
Correction attendue
Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Limiter les données sensibles accessibles dans le DOM, éviter les tokens persistants dans localStorage, préférer cookies HttpOnly pour sessions web, isoler les privilèges admin, ajouter confirmations serveur pour actions sensibles et surveiller les comportements anormaux post-XSS.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
HttpOnlyRéduit le vol direct du cookie par JS.
SecureTransmission uniquement via HTTPS.
SameSiteRéduit certains envois cross-site.
localStorageAccessible au JavaScript injecté : prudence maximale.
Actions sensiblesRevalidation, MFA step-up, anti-CSRF et logs.
Checklist
  • Vérifier flags cookies en production.
  • Éviter tokens sensibles dans localStorage.
  • Segmenter les sessions admin.
  • Ajouter step-up pour actions critiques.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
12. Frameworks modernes — Django, React, Vue, Angular et composants tiers
Frameworks modernes

Les frameworks modernes protègent contre beaucoup de XSS classiques grâce à l’échappement automatique et aux abstractions DOM. Mais ces protections tombent dès que le code contourne le rendu normal : safe/raw, mark_safe, dangerouslySetInnerHTML, v-html, bypassSecurityTrust*, templates inline, HTML tiers ou manipulation DOM directe.

DjangoReactTemplates
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Frameworks modernesSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

La règle est simple : rester dans le chemin sûr du framework. Dans Django, l’autoescape protège le rendu HTML standard ; les filtres safe/mark_safe doivent être exceptionnels. Dans React, l’interpolation texte est échappée ; dangerouslySetInnerHTML doit être réservé au HTML sanitizé. Dans Angular, les bypass de sanitizer sont des exceptions de sécurité. Les composants tiers doivent être considérés comme code exécutable importé.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Chemins sûrs et dangereux
Anti-pattern
React : <div dangerouslySetInnerHTML={{ __html: userHtml }} />
Django : {{ user_html|safe }}
Correction attendue
React : <div>{userText}</div>
Django : {{ user_text }}
HTML riche : sanitizer central + revue sécurité.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Créer une politique d’usage par framework. Bloquer les exceptions dans les linters lorsque possible. Encapsuler les rendus HTML riches dans un composant unique, testé, documenté et surveillé. Refuser les composants tiers qui injectent du HTML sans contrôle.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
DjangoAutoescape par défaut ; prudence safe/mark_safe.
ReactInterpolation sûre ; danger sur dangerouslySetInnerHTML.
VueMoustaches sûres ; danger sur v-html.
AngularSanitization intégrée ; danger sur bypassSecurityTrust*.
jQuery legacyhtml() dangereux avec données non fiables.
Checklist
  • Scanner les contournements framework.
  • Créer une liste d’exceptions approuvées.
  • Auditer composants tiers et éditeurs riches.
  • Former les équipes front/back sur les contextes.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
13. Détection et tests — SAST, DAST, revue manuelle et tests navigateur
Détection et tests

La détection XSS combine plusieurs approches. Le SAST repère les flux source → sink dans le code. Le DAST observe le comportement de l’application. La revue manuelle identifie les contextes subtils. Les tests navigateur détectent le DOM XSS, les comportements de composants et les régressions CSP. Aucun outil ne couvre tout seul l’ensemble des cas.

SASTDASTQA
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Détection et testsSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Un bon plan de test commence par l’inventaire des entrées : formulaires, URL, API, import fichiers, WebSocket, postMessage, Markdown, WYSIWYG, logs, champs admin. Chaque entrée est suivie jusqu’aux sorties. Les tests doivent utiliser des chaînes canaris neutralisées qui révèlent les changements de contexte sans déclencher de charge agressive.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Canari neutralisé
Anti-pattern
Test limité à “le champ est validé en entrée”.
Correction attendue
Injecter une chaîne canari encodée dans chaque champ, puis vérifier tous les rendus : front, admin, email HTML, export, logs, notifications.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Intégrer les tests XSS dans CI/CD : règles Semgrep/CodeQL, tests Playwright/Cypress, scan DAST en préproduction, revue des CSP reports et couverture des templates. Les findings doivent indiquer contexte, source, sink, impact et correction recommandée.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
SASTTrouve patterns dangereux dans le code.
DASTObserve réponses et comportements applicatifs.
IA/assistant codeAide à repérer anti-patterns, mais nécessite validation.
Manual reviewIndispensable pour contextes complexes.
Browser testsNécessaires pour DOM XSS et CSP.
Checklist
  • Inclure XSS dans la définition de terminé.
  • Tester front public et back-office.
  • Automatiser recherche safe/raw/innerHTML.
  • Documenter chaque correction avec contexte exact.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
14. WAF / WAAP et limites — Filtrer ne remplace pas corriger
WAF / WAAP et limites

Un WAF ou WAAP peut réduire l’exposition, bloquer des patterns connus, ralentir l’exploitation et fournir de la télémétrie. Il ne remplace pas l’encodage contextuel, la sanitation ni la correction de code. Le XSS dépend du contexte applicatif ; un filtre réseau ne sait pas toujours comment le navigateur interprétera la donnée finale.

WAFWAAPDefense in depth
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
WAF / WAAP et limitesSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Les filtres génériques peuvent produire des faux positifs, rater des encodages alternatifs, ignorer le DOM XSS client ou bloquer des usages légitimes. Ils sont utiles comme couche de protection, notamment lors d’une crise ou en attente de patch, mais la correction durable doit se situer dans le rendu applicatif et les composants front-end.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Positionnement correct
Anti-pattern
Finding XSS fermé parce que “le WAF bloque la chaîne de test”.
Correction attendue
WAF utilisé en mitigation temporaire ; ticket de correction maintenu jusqu’à encodage/sanitation côté application.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Définir le WAF comme contrôle compensatoire. Surveiller les faux positifs, conserver les logs, corréler avec les endpoints vulnérables et retirer les règles temporaires après correction. Ne pas exposer d’exception globale qui affaiblit toute l’application.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
ForcesBlocage rapide, visibilité, règles virtuelles temporaires.
LimitesContexte incomplet, DOM XSS, contournements, faux positifs.
Bon usageMitigation en profondeur et protection transitoire.
Mauvais usageRemplacer la correction applicative par une règle réseau.
Checklist
  • Marquer les règles WAF temporaires.
  • Relier chaque règle à un ticket de correction.
  • Analyser les endpoints les plus touchés.
  • Ne jamais considérer le WAF comme unique défense XSS.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
15. Réponse à incident XSS — Contenir, enquêter, corriger et communiquer
Réponse à incident XSS

Lorsqu’un XSS est exploité, l’incident ne se limite pas au patch. Il faut identifier les victimes potentielles, les actions effectuées dans leurs sessions, les données consultées, les contenus stockés, la persistance éventuelle et les comptes à privilèges exposés. Le périmètre dépend du type de XSS, des logs disponibles et des protections de session.

IncidentSOCForensics
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Réponse à incident XSSSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

La chronologie doit relier point d’entrée, payload neutralisé ou contenu suspect, première apparition, pages touchées, comptes victimes, appels API anormaux, changements de configuration, transferts de données et éventuelles escalades. En cas de stored XSS, la suppression ou neutralisation du contenu stocké est prioritaire avant même la correction complète.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Runbook court
Anti-pattern
Corriger le template puis fermer l’incident sans vérifier les sessions et actions passées.
Correction attendue
Neutraliser le contenu, bloquer exploitation, invalider sessions exposées, analyser logs, corriger, déployer CSP/monitoring, rédiger post-mortem.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Préparer des playbooks : purge contenu, invalidation sessions, rotation tokens, désactivation temporaire de rendu HTML riche, règle WAF transitoire, collecte CSP reports, revue des comptes admin et communication conforme au niveau de risque.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
ContainmentSupprimer contenu stocké, règle temporaire, désactivation feature.
EradicationCorrection contextuelle, tests de non-régression.
RecoveryRedéploiement, monitoring, rotation sessions/tokens.
Lessons learnedComposant commun, linter, formation, tests CI.
Checklist
  • Conserver les preuves avant purge si possible.
  • Invalider les sessions à risque.
  • Vérifier actions sensibles réalisées pendant la fenêtre.
  • Ajouter tests et règles de détection après correction.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
16. Mini-lab pédagogique — Apprendre sans mettre en danger
Mini-lab pédagogique

Un apprentissage efficace du XSS repose sur des exercices courts : identifier le contexte, choisir la défense, corriger le code, vérifier que le rendu reste fonctionnel. Un mini-lab interne peut proposer des chaînes canaris inoffensives, des templates volontairement vulnérables et des corrections guidées, sans fournir de charges orientées vol de données ou contournement offensif.

LudiqueLabDidactique
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Mini-lab pédagogiqueSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Le jeu pédagogique peut suivre un format en quatre cartes : source, contexte, sink, correction. L’apprenant reçoit un extrait de code, identifie le contexte de sortie, choisit la bonne API ou le bon encodage, puis vérifie le résultat. Les scores ne récompensent pas l’attaque, mais la correction : suppression du sink dangereux, choix du contexte, test de non-régression et explication claire.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Carte de jeu
Anti-pattern
Niveau 1 : “Le message utilisateur est rendu avec innerHTML. Trouver le problème.”
Correction attendue
Solution : remplacer par textContent, ajouter test, expliquer pourquoi la donnée devait rester du texte.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Les labs doivent être isolés, non connectés à des données réelles, sans authentification production et avec des payloads neutralisés. L’objectif est la maîtrise des défenses et du raisonnement par contexte.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
Niveau 1HTML body : escaping simple.
Niveau 2Attribut href : validation schéma + encodage.
Niveau 3DOM XSS : source → sink.
Niveau 4HTML riche : sanitizer + CSP.
Niveau 5Incident : containment + correction + post-mortem.
Checklist
  • Créer des exercices par contexte.
  • Utiliser des chaînes canaris neutralisées.
  • Noter la correction, pas la charge.
  • Intégrer les résultats à la formation développeur.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
17. Architecture anti-XSS — Contrôles empilés du code au navigateur
Architecture anti-XSS

Une architecture anti-XSS robuste combine des contrôles au niveau code, template, framework, composants front-end, headers HTTP, sessions, dépendances, tests et supervision. La meilleure défense est un chemin sûr par défaut : les développeurs n’ont pas à se souvenir de chaque règle si les composants communs rendent les mauvais choix difficiles.

ArchitectureSecure by designSDLC
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Architecture anti-XSSSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Le modèle cible impose : autoescape actif, composants de rendu communs, helper unique pour HTML riche, sanitizer central, CSP stricte, Trusted Types pour les applications compatibles, cookies durcis, linters anti-sinks, tests CI, revue des exceptions, inventaire des composants tiers et observabilité CSP. Les exceptions existent, mais elles sont documentées, validées et révisées.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Pipeline sécurisé
Anti-pattern
Chaque équipe choisit ses propres helpers, sanitizers et exceptions safe/raw.
Correction attendue
Bibliothèque interne de rendu : Text, SafeLink, RichHtmlSanitized, JsonScript, MarkdownSafe, tous testés et documentés.
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Mettre la sécurité dans les abstractions : composants UI, middlewares, headers, templates de base, conventions de code, CI/CD et revues. Les règles doivent être visibles dans le dépôt et vérifiées automatiquement.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
CodeAPIs sûres, pas de sink brut.
TemplateAutoescape, helpers contextuels.
NavigateurCSP, Trusted Types, headers de sécurité.
SessionCookies durcis, step-up actions sensibles.
SDLCSAST/DAST/tests/revue exceptions.
Checklist
  • Créer des composants de rendu communs.
  • Bloquer les patterns dangereux en CI.
  • Standardiser CSP et cookies.
  • Revoir régulièrement les exceptions.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
18. Cheat-sheet finale — Décisions rapides, checklist et références
Cheat-sheet finale

La prévention XSS peut se résumer en une phrase : une donnée non fiable doit rester du texte, sauf décision explicite, contrôlée et testée de l’interpréter autrement. Les mécanismes de sécurité doivent être contextuels, centralisés, testés et observables.

SynthèseChecklistRéférences
Principe : une donnée non fiable ne doit jamais changer de nature. Elle reste du texte, sauf décision explicite, contrôlée et testée de la rendre interprétable.
Cheat-sheet finaleSource → contexte → contrôle → rendu → navigateur → mesureEntrée non fiableURL · formulaire · APIContexteHTML · attr · JS · URLContrôleencode · sanitize · validateRendutemplate · DOM · composantNavigateurparse · exécute · bloqueMesuretests · CSP · logsPréventionéchapper · valider · sanitiserRéduction d’impactCSP · cookies · isolationAssurancetests · revue · monitoring
Mécanique

Le réflexe opérationnel suit cinq questions : quelle est la source ? quel est le contexte de sortie ? quel sink reçoit la donnée ? quelle défense est appliquée ? quel test prouve que le navigateur ne change pas d’interprétation ? Si une seule réponse manque, la zone mérite une revue.

Vigilance : le XSS est une vulnérabilité de contexte. Une correction correcte dans une zone peut rester insuffisante si la même donnée est réutilisée ailleurs.
Chaîne source → sink
Source non fiable
  ↓
Transformation / stockage
  ↓
Contexte de sortie
  ↓
Sink de rendu
  ↓
Interprétation navigateur
  ↓
Test + monitoring
Décision express
Anti-pattern
“Le champ est validé, donc il est sûr partout.”
Correction attendue
“La sortie est en contexte HTML texte, donc autoescape suffit ; si le contexte change, la défense change.”
Raison pédagogique

L’exemple illustre le raisonnement de défense, sans fournir de scénario offensif ni de contournement. L’objectif est de reconnaître le mauvais contexte, de choisir l’API sûre et de documenter la correction.

Test de validation : une chaîne contenant des caractères spéciaux doit s’afficher comme texte visible, sans créer de balise, d’attribut, d’événement, de script ou d’URL active.
Défenses recommandées

Priorités : supprimer safe/raw injustifiés, remplacer innerHTML par textContent, centraliser le HTML riche, mettre CSP en report-only puis enforcement, durcir cookies, scanner sources/sinks et former les équipes sur les contextes.

Prévenir
  • Encodage contextuel.
  • APIs textuelles par défaut.
  • Sanitizer pour HTML riche.
Réduire l’impact
  • CSP stricte.
  • Cookies HttpOnly/Secure/SameSite.
  • Permissions minimales.
À éviter
  • safe/raw non justifié.
  • innerHTML avec données non fiables.
  • Regex maison pour nettoyer du HTML.
Tableau opérationnel
PointLecture opérationnelle
Règle 1Encoder à la sortie selon le contexte.
Règle 2Préférer les APIs textuelles aux APIs HTML.
Règle 3Sanitizer uniquement pour HTML riche nécessaire.
Règle 4CSP/Trusted Types comme filets de sécurité.
Règle 5Tester front, back-office, exports et emails HTML.
Checklist
  • Aucun raw/safe non justifié.
  • Aucun innerHTML avec données non fiables.
  • HTML riche centralisé et sanitizé.
  • CSP active et surveillée.
  • Tests XSS intégrés au CI/CD.
Critère de sortie

La zone est considérée maîtrisée lorsque le contexte de rendu est identifié, la défense est contextuelle, les tests confirment l’absence d’interprétation active et les exceptions sont documentées.

Livrable attendu : source, sink, contexte, correction, test, propriétaire et date de revue.
Références XSS — liens utiles
Usage : ces références complètent le guide. Elles servent à valider les règles d’encodage, approfondir les types de XSS, structurer les tests et renforcer les défenses navigateur.
SourceIntérêt
OWASP XSS Prevention Cheat SheetRègles d’encodage contextuel et recommandations de prévention.
OWASP DOM based XSS Prevention Cheat SheetRaisonnement sources/sinks et sous-contextes DOM.
OWASP Community — Cross Site ScriptingDéfinition générale et typologie de l’attaque.
OWASP Top 10 — A03 InjectionPositionnement XSS dans la famille Injection.
PortSwigger Web Security Academy — XSSCours et labs de référence sur reflected, stored et DOM XSS.
MDN — Cross-site scriptingExplication navigateur et défenses côté plateforme web.
MDN — Content Security PolicyGuide CSP et directives de protection.
MDN — Trusted Types APIAPI Trusted Types pour réduire les sinks DOM dangereux.
Django Security DocumentationProtection XSS et sécurité intégrée du framework Django.
DOMPurifySanitizer HTML/SVG/MathML largement utilisé côté client et serveur.