Content-Security-Policy : Protéger votre site sans bloquer vos utilisateurs

Introduction

La Content-Security-Policy (CSP) est l’un des outils les plus puissants de la sécurité web moderne. Pourtant, elle est aussi l’une des plus redoutées. Mal configurée, elle peut casser des fonctionnalités critiques de votre site. Bien configurée, elle offre une protection redoutable contre les attaques XSS, les injections de scripts et les chargements externes non maîtrisés.

Dans cet article, nous allons explorer pas à pas :

  • Ce qu’est la Content-Security-Policy
  • Comment la configurer dans Nginx
  • Comment éviter de bloquer le bon fonctionnement du site
  • Et comment la tester et l’ajuster en toute sécurité

Qu’est-ce qu’une Content-Security-Policy (CSP) ?

La CSP est un header HTTP qui indique au navigateur quelles ressources il est autorisé à charger (scripts, styles, images, etc.) et depuis quelles sources.

Son objectif principal : empêcher l’exécution de contenu non prévu dans la page, comme un script malveillant injecté par un attaquant (attaque XSS).

Prenons un exemple simple :

Content-Security-Policy: default-src 'self'

Cette directive interdit au navigateur de charger des ressources (scripts, images, etc.) depuis des domaines autres que le vôtre.


Pourquoi mettre en place une CSP ?

Voici quelques bénéfices clés :

  • Empêche les scripts injectés (XSS) d’être exécutés
  • Bloque les ressources non autorisées (ex. CDN tiers non validés)
  • Évite les attaques de type data exfiltration (ex. chargement d’images depuis un domaine pirate pour récupérer des infos)
  • Protège les utilisateurs avec un niveau de sécurité élevé
  • ✅ Recommandé par l’OWASP et Mozilla

Exemple d’attaque sans CSP

Un champ de commentaire non protégé peut permettre à un utilisateur malveillant d’injecter :

<script>alert('Vous avez été piraté');</script>

Sans CSP, le navigateur l’exécutera. Avec une bonne politique, il le bloquera purement et simplement.


Intégrer une CSP dans Nginx

Dans Nginx, la CSP se configure via une directive add_header dans votre bloc server {} ou location {}.

Exemple basique :

add_header Content-Security-Policy "default-src 'self'" always;

Mais en pratique, cela cassera tous vos scripts, styles et ressources provenant de CDNs externes (Bootstrap, jQuery, Google Fonts…).


Une configuration CSP souple et sécurisée

Voici une configuration équilibrée qui couvre la majorité des sites modernes sans tout bloquer :

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https: data:; connect-src 'self' https:; frame-ancestors 'self';" always;

Détails des directives :

  • default-src 'self' : autorise uniquement les ressources locales par défaut
  • script-src : autorise JS inline (si nécessaire) + sources HTTPS
  • style-src : idem pour les feuilles CSS
  • img-src : autorise les images locales, en base64 (data:) et via CDN
  • font-src : autorise les polices locales + Google Fonts
  • connect-src : autorise les connexions Ajax/Fetch/WebSocket
  • frame-ancestors 'self' : empêche l’intégration dans une iframe par un autre domaine

💡 Tu peux affiner chaque directive selon les besoins de ton site.


CSP et environnement frontend moderne

Si tu utilises un framework comme Vue, React, Angular ou un CMS comme WordPress, il faut adapter la CSP :

  • WordPress + Elementor : attention à unsafe-inline pour les styles et scripts dans les shortcodes.
  • React / Vue avec Webpack : éviter unsafe-eval si possible.
  • CDN (Bootstrap, jQuery) : autorise https: dans script-src et style-src.

Exemple spécifique WordPress avec CDN :

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://code.jquery.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com;" always;

Astuce : mode report-only pour tester sans casser

Avant d’activer ta politique CSP, tu peux la tester en mode report-only. Cela permet de voir les violations sans bloquer les ressources :

add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' https:;" always;

Couple ça avec une plateforme de monitoring CSP comme :


Où ajouter la CSP dans Nginx ?

Toujours dans le bloc server {} ou directement dans un location si tu veux l’appliquer uniquement sur des zones sensibles (/admin, /login, etc.)

Important : ajoute always pour que le header soit appliqué même sur les pages 404/500.


Conseils pratiques

  • 🔁 Teste ta CSP sur un environnement de staging avant production
  • ✅ Utilise report-only pour analyser sans casse
  • 🔍 Inspecte les erreurs CSP dans la console développeur de ton navigateur
  • 🧪 Utilise csp-evaluator pour voir les failles potentielles
  • ❌ Évite unsafe-inline et unsafe-eval si ton frontend le permet
  • 🧩 Ne bloque jamais img-src data: si tu utilises des images en base64 (ex. avatars dans WordPress)

Tester votre configuration

Voici les meilleurs outils pour valider ta politique CSP :

Avec une CSP bien configurée, ton site obtiendra facilement un score A ou A+ sur ces plateformes.


Cas réel : CSP dans un contexte scolaire (site avec sous-répertoires)

Si tu héberges des applications ou sites étudiants dans des sous-répertoires (/tata, /toto, etc.), tu peux appliquer une CSP globale dans un bloc avec regex :

location ~ ^/([a-z0-9-]+)(/.*)?$ {
    root /home/app/htdocs;
    try_files $uri $uri/ /$1/index.php?$args;

    add_header Content-Security-Policy "default-src 'self'; script-src 'self' https:;" always;
}

En résumé

  • ✅ La Content-Security-Policy protège contre les attaques XSS et injections
  • ⚙️ Elle se configure facilement dans Nginx avec add_header
  • 🎯 Elle peut être testée en mode report-only pour éviter de casser ton site
  • 🔒 Elle est recommandée par tous les standards modernes (OWASP, Mozilla, Google)
  • 💡 Elle doit être adaptée à ton environnement technique

Ressources utiles