XSS en Angular : Bonnes pratiques & DomSanitizer

🏷️ Front-end 📅 01/04/2026 13:00:00 👤 Mezgani Said
Angular Sécurité Xss Sanitizer
XSS en Angular : Bonnes pratiques & DomSanitizer

Prévention XSS en Angular : sanitization automatique, DomSanitizer, trusted HTML/URL, Content Security Policy et bonnes pratiques de sécurité.

Introduction

Les attaques XSS (Cross-Site Scripting) figurent au TOP 3 des vulnérabilités OWASP. Elles injectent du code malveillant dans votre application pour voler des données ou contrôler les sessions. Angular vous protège automatiquement grâce à un système de sanitization intégré, mais il faut comprendre comment ça marche.

Risque réel : Un attaquant vole les cookies de session d'un utilisateur, accède à son compte, ou redirige vers un phishing. C'est grave. Angular + bonnes pratiques = protection complète.

Qu'est-ce que le XSS ?

XSS signifie "injecter du code malveillant (JavaScript) qui s'exécute dans le navigateur de vos utilisateurs". Exemple :

// Commentaire d'un utilisateur malveillant
const evilComment = `
    <script>
        fetch('/api/steal-session', {
            method: 'POST',
            body: JSON.stringify({ cookie: document.cookie })
        });
    </script>
`;

// Si vous l'affichez sans protection dans les commentaires :
// Le script s'exécute dans le navigateur de TOUS les visiteurs
// ➜ Les cookies de session de chacun sont envoyés au serveur attaquant
Les 3 types de XSS :
  • Stored XSS : Le code malveillant est stocké en BD (commentaires, posts, profils). Le plus dangereux.
  • Reflected XSS : Le code vient de l'URL (paramètres GET). Ex: example.com/search?q=<script>alert('xss')</script>
  • DOM XSS : JavaScript côté client modifie le DOM de manière non sécurisée. Ex: element.innerHTML = userInput

Protection automatique d'Angular

Par défaut, Angular échappe automatiquement tous les caractères dangereux quand vous utilisez l'interpolation {{}} :

// component.ts
export class CommentComponent {
    userComment = '<script>alert("XSS")</script>';
    otherComment = '<img src=x onerror="alert(\'XSS\')">';
}

// template.html — SÉCURISÉ ✅
<p>{{ userComment }}</p>
<p>{{ otherComment }}</p>

// Rendu HTML : Les balises sont écrites en texte, pas exécutées
// <p>&lt;script&gt;alert("XSS")&lt;/script&gt;</p>
// <p>&lt;img src=x onerror="alert('XSS')"&gt;</p>
Qu'est-ce que l'échappement ? Angular remplace :
  • <&lt;
  • >&gt;
  • "&quot;
  • '&#39;
Le navigateur les affiche comme texte, pas comme code HTML/JavaScript.

DomSanitizer — Quand vous avez besoin de HTML

Parfois, vous DEVEZ afficher du HTML riche (contenu d'éditeur, markdown compilé, etc.). C'est là qu'intervient DomSanitizer :

// component.ts
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { SecurityContext } from '@angular/core';

@Component({
    selector: 'app-rich-content',
    template: '<div [innerHTML]="safeHtml"></div>'
})
export class RichContentComponent {
    safeHtml: SafeHtml;

    constructor(private sanitizer: DomSanitizer) {
        // Contenu provenant d'un éditeur riche (WYSIWYG)
        const htmlFromEditor = `
            <h2>Mon article</h2>
            <p>Texte en <strong>gras</strong></p>
            <img src="image.jpg" alt="Mon image">
            <script>alert('Hack!')</script>  <!-- Sera supprimé -->
        `;

        // Option 1 : Nettoyer en supprimant les balises dangereuses
        this.safeHtml = this.sanitizer.sanitize(
            SecurityContext.HTML,
            htmlFromEditor
        );

        // Option 2 : Trusted HTML (dangereux, utilisez avec prudence)
        // this.safeHtml = this.sanitizer.bypassSecurityTrustHtml(htmlFromEditor);
    }
}
⚠️ Attention :
  • sanitize() → Nettoie en supprimant les balises XSS (recommandé)
  • bypassSecurityTrustHtml() → Fait confiance au HTML (dangereux, à éviter)

Checklist de sécurité XSS

  • Utiliser {{}} — Angular échappe automatiquement. C'est votre arme principale.
  • [property] → safe. Ex: [title]="userInput"
  • [attr.href] → safe. Angular vérifie l'URL.
  • DomSanitizer.sanitize() → Safe pour le HTML riche (supprime les scripts).
  • [innerHTML] → Dangereux sans DomSanitizer. Chaque {{ }} est plus sûr.
  • bypassSecurityTrustHtml() → Très dangereux. Utilisez seulement si vous contrôlez 100% le contenu.
  • eval(userInput) → Crime de sécurité. Jamais.
  • new Function(userInput) → Pareil. Jamais.
En production :
  • Validez TOUJOURS les entrées utilisateur (côté serveur)
  • Activez une Content Security Policy (CSP) header
  • Scannez vos dépendances npm avec npm audit
  • Utilisez ng-csp-nonce pour les CSP nonce-based

Conclusion

Angular vous protège par défaut. Mais vous devez comprendre les règles :

  • {{}} = Safe ✅ (le 99% de vos cas)
  • [innerHTML] + DomSanitizer.sanitize() = Safe ✅ (HTML riche)
  • [innerHTML] + bypassSecurityTrustHtml() = Dangereux ⚠️ (seulement si you control 100%)
  • eval(), new Function() = Crime 🔴 (jamais)
Règle d'or : Ne faites JAMAIS confiance à l'entrée utilisateur. Toujours valider au serveur. Toujours échapper en affichant. Si vous êtes en doute, utilisez {{}} — c'est toujours safe.