Pourquoi la Content Security Policy est devenue incontournable

En 2024, le rapport de l’OWASP place toujours les attaques par injection — dont le Cross-Site Scripting (XSS) — parmi les trois menaces les plus critiques pour les applications web. Selon une étude de Positive Technologies, près de 70 % des applications web testées présentaient au moins une vulnérabilité XSS. Face à ce constat, la Content Security Policy (CSP) s’impose comme l’un des mécanismes de défense les plus efficaces.

Pourtant, d’après les relevés du HTTP Archive, moins de 15 % des sites web déploient une CSP correctement configurée. Un chiffre qui laisse songeur quand on sait qu’une CSP rigoureuse peut neutraliser plus de 90 % des vecteurs d’attaque XSS.

Cet article vous guide pas à pas dans la compréhension, la configuration et le déploiement de la Content Security Policy et des en-têtes de sécurité HTTP complémentaires.

Comprendre la Content Security Policy

Le principe de fonctionnement

La CSP est un en-tête HTTP envoyé par votre serveur au navigateur du visiteur. Cet en-tête contient une liste blanche de sources autorisées pour chaque type de ressource : scripts, feuilles de style, images, polices, iframes, etc.

Lorsqu’un navigateur reçoit cette politique, il bloque automatiquement toute ressource qui ne correspond pas aux règles définies. Si un attaquant parvient à injecter un script malveillant dans votre page, le navigateur refusera de l’exécuter car la source ne figure pas dans la liste autorisée.

Les directives principales

Une politique CSP se compose de directives, chacune contrôlant un type de ressource spécifique :

DirectiveContrôleExemple de valeur
default-srcSource par défaut pour tout contenu'self'
script-srcScripts JavaScript'self' https://cdn.exemple.com
style-srcFeuilles de style CSS'self' 'unsafe-inline'
img-srcImages'self' data: https:
font-srcPolices de caractères'self' https://fonts.gstatic.com
connect-srcRequêtes AJAX, WebSocket, EventSource'self' https://api.exemple.com
frame-srcSources autorisées pour les iframeshttps://www.youtube.com
object-srcPlugins (Flash, Java)'none'
base-uriRestreint les URL dans <base>'self'
form-actionURLs autorisées pour les soumissions de formulaires'self'
frame-ancestorsQui peut intégrer votre page en iframe'none'
report-uriURL de réception des rapports de violation/csp-report-endpoint

La directive default-src agit comme un filet de sécurité : elle s’applique à tous les types de ressources pour lesquels vous n’avez pas défini de directive spécifique.

Les valeurs spéciales

Certaines valeurs entre guillemets simples ont une signification particulière :

  • 'self' : autorise les ressources provenant du même domaine
  • 'none' : bloque totalement ce type de ressource
  • 'unsafe-inline' : autorise le CSS ou JS inline (déconseillé)
  • 'unsafe-eval' : autorise eval() et les fonctions similaires (déconseillé)
  • 'nonce-abc123' : autorise les éléments portant l’attribut nonce="abc123"
  • 'sha256-...' : autorise un script/style dont le hash correspond

Configurer sa première Content Security Policy

Étape 1 : Inventorier les ressources de votre site

Avant d’écrire la moindre règle, vous devez cartographier toutes les ressources externes chargées par votre site :

  • Scripts JavaScript (analytics, chatbot, réseaux sociaux, librairies CDN)
  • Feuilles de style et polices (Google Fonts, Font Awesome)
  • Images et médias (CDN d’images, vidéos YouTube ou Vimeo)
  • Requêtes AJAX (API tierces, passerelles de paiement)
  • Iframes (cartes Google Maps, lecteurs vidéo, widgets)

Ouvrez les DevTools de votre navigateur (F12), onglet Network, et naviguez sur l’ensemble de votre site pour identifier toutes ces ressources.

Étape 2 : Rédiger la politique

Voici un exemple de CSP pour un site e-commerce sous PrestaShop utilisant Google Analytics, Google Fonts et un lecteur YouTube :

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com 'nonce-RANDOM_NONCE';
  style-src 'self' https://fonts.googleapis.com 'nonce-RANDOM_NONCE';
  img-src 'self' data: https://www.google-analytics.com https://*.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://www.google-analytics.com https://analytics.google.com;
  frame-src https://www.youtube.com https://www.google.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'self';
  upgrade-insecure-requests;

Quelques points essentiels à retenir :

  • Commencez toujours par default-src 'self' pour verrouiller par défaut
  • Utilisez des nonces plutôt que 'unsafe-inline' pour autoriser les scripts et styles inline spécifiques
  • object-src 'none' bloque les plugins obsolètes comme Flash
  • upgrade-insecure-requests force automatiquement les requêtes HTTP vers HTTPS

Étape 3 : Déployer en mode Report-Only

C’est l’étape la plus importante — et la plus souvent négligée. Ne déployez jamais une CSP directement en production sans phase de test.

Utilisez l’en-tête Content-Security-Policy-Report-Only :

Content-Security-Policy-Report-Only:
  default-src 'self';
  script-src 'self' https://www.googletagmanager.com;
  report-uri /csp-report;
  report-to csp-endpoint;

Dans ce mode, le navigateur ne bloque rien mais vous envoie un rapport JSON à chaque violation. Analysez ces rapports pendant une à deux semaines pour affiner votre politique avant de l’activer.

Chez Lueur Externe, cette phase de monitoring préalable fait partie intégrante de notre processus de déploiement CSP. En tant qu’agence spécialisée dans la sécurité web depuis 2003, nous avons constaté que cette approche progressive évite les incidents en production dans 100 % des cas.

Étape 4 : Implémenter sur votre serveur

Voici comment ajouter l’en-tête CSP selon votre environnement :

Apache (.htaccess ou vhost) :

<IfModule mod_headers.c>
  Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' https://fonts.googleapis.com; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com; object-src 'none'; frame-ancestors 'self'; upgrade-insecure-requests;"
</IfModule>

Nginx :

add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' https://fonts.googleapis.com; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com; object-src 'none'; frame-ancestors 'self'; upgrade-insecure-requests;" always;

PHP (WordPress, PrestaShop) :

<?php
header("Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' https://fonts.googleapis.com; object-src 'none';");

Les autres en-têtes de sécurité HTTP indispensables

La CSP ne fonctionne pas seule. Pour une protection complète, vous devez configurer un ensemble d’en-têtes complémentaires.

X-Content-Type-Options

Cet en-tête empêche le navigateur de deviner (“sniffer”) le type MIME d’une ressource. Sans lui, un fichier texte contenant du JavaScript pourrait être interprété comme un script.

X-Content-Type-Options: nosniff

Configuration simple, impact majeur. Il n’y a aucune raison de ne pas l’activer.

X-Frame-Options

Protège contre le clickjacking en contrôlant qui peut intégrer votre site dans une iframe. Bien que frame-ancestors dans la CSP offre plus de granularité, X-Frame-Options reste nécessaire pour la compatibilité avec les anciens navigateurs.

X-Frame-Options: SAMEORIGIN

Strict-Transport-Security (HSTS)

Force les navigateurs à n’utiliser que HTTPS pour communiquer avec votre site, même si l’utilisateur tape http:// :

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • max-age=31536000 : politique valable 1 an (en secondes)
  • includeSubDomains : applique la règle à tous les sous-domaines
  • preload : permet l’inclusion dans la liste HSTS préchargée des navigateurs

Referrer-Policy

Contrôle les informations de provenance transmises lorsqu’un utilisateur clique sur un lien sortant :

Referrer-Policy: strict-origin-when-cross-origin

Cette valeur offre un bon équilibre entre fonctionnalité (les outils analytics reçoivent toujours l’origine) et confidentialité (le chemin complet de l’URL n’est pas transmis aux sites tiers).

Permissions-Policy

Successeur de Feature-Policy, cet en-tête contrôle l’accès aux fonctionnalités du navigateur comme la caméra, le micro ou la géolocalisation :

Permissions-Policy: camera=(), microphone=(), geolocation=(self), payment=(self)

Les parenthèses vides () désactivent totalement la fonctionnalité. C’est une protection supplémentaire contre les scripts tiers qui tenteraient d’accéder à des API sensibles.

Configuration complète recommandée

Voici un bloc Apache regroupant tous les en-têtes de sécurité essentiels :

<IfModule mod_headers.c>
  # Content Security Policy
  Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'; upgrade-insecure-requests;"

  # Autres en-têtes de sécurité
  Header set X-Content-Type-Options "nosniff"
  Header set X-Frame-Options "SAMEORIGIN"
  Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
  Header set Referrer-Policy "strict-origin-when-cross-origin"
  Header set Permissions-Policy "camera=(), microphone=(), geolocation=(self)"
  Header set X-XSS-Protection "0"
</IfModule>

Note : X-XSS-Protection: 0 est désormais la recommandation officielle. Ce filtre, présent dans les anciens navigateurs, peut paradoxalement introduire des vulnérabilités. La CSP le remplace avantageusement.

Cas particuliers et pièges courants

WordPress et les scripts inline

WordPress utilise massivement les scripts et styles inline, ce qui complique la mise en place d’une CSP stricte. Deux approches sont possibles :

  1. Les nonces : WordPress 5.7+ supporte les nonces CSP via le filtre wp_script_attributes. Chaque chargement de page génère un nonce unique qui autorise les scripts inline légitimes.
  2. Les hash : calculez le hash SHA-256 de chaque script inline statique et ajoutez-le à votre directive script-src.

Évitez autant que possible 'unsafe-inline' qui annule la quasi-totalité de la protection contre le XSS.

PrestaShop et les modules tiers

L’écosystème PrestaShop repose sur de nombreux modules qui injectent leurs propres scripts et styles. L’expérience de Lueur Externe, agence certifiée PrestaShop, montre qu’un audit module par module est indispensable avant tout déploiement de CSP. Certains modules mal codés utilisent eval() ou des scripts inline sans nonce, nécessitant soit une correction du code, soit une exception dans la politique.

Google Tag Manager

GTM est particulièrement complexe à gérer avec une CSP stricte car il charge dynamiquement des scripts de sources variées. La solution recommandée est :

  • Autoriser https://www.googletagmanager.com dans script-src
  • Utiliser le mode nonce de GTM (disponible dans les paramètres avancés du conteneur)
  • Lister explicitement chaque service tiers chargé via GTM

Les erreurs fréquentes à éviter

  • CSP trop permissive : utiliser script-src 'self' 'unsafe-inline' 'unsafe-eval' https: revient à n’avoir presque aucune protection
  • Oublier des directives : sans object-src 'none', les plugins Flash restent un vecteur d’attaque
  • Ne pas tester : déployer en production sans phase Report-Only peut casser des fonctionnalités critiques (paiement, formulaires, analytics)
  • Politique statique : votre CSP doit évoluer avec votre site. Chaque nouveau service tiers doit être évalué et ajouté

Mesurer l’efficacité de votre configuration

Les outils de test

Plusieurs outils gratuits vous permettent de vérifier la qualité de vos en-têtes de sécurité :

  • SecurityHeaders.com : note de A+ à F avec des recommandations claires
  • CSP Evaluator de Google : analyse la robustesse de votre politique CSP
  • Mozilla Observatory : audit complet incluant CSP, HSTS, et autres bonnes pratiques
  • Lighthouse (DevTools Chrome) : intègre des vérifications de sécurité dans ses audits

Visez au minimum une note A sur SecurityHeaders.com. Selon nos relevés chez Lueur Externe, les sites que nous sécurisons atteignent systématiquement la note A+ après optimisation complète des en-têtes.

Monitoring continu des violations

Mettez en place un endpoint de reporting pour collecter les violations CSP en temps réel. Vous pouvez utiliser des services comme Report URI ou implémenter votre propre collecteur :

// Exemple simplifié de collecteur de rapports CSP (Node.js/Express)
app.post('/csp-report', express.json({ type: 'application/csp-report' }), (req, res) => {
  const violation = req.body['csp-report'];
  console.log('Violation CSP détectée:', {
    directive: violation['violated-directive'],
    source: violation['blocked-uri'],
    page: violation['document-uri']
  });
  // Stocker en base, alerter par email, etc.
  res.status(204).end();
});

Ce monitoring vous permet de détecter :

  • Des tentatives d’attaque XSS en temps réel
  • Des ressources légitimes oubliées dans votre politique
  • Des modules ou extensions navigateur qui tentent d’injecter du contenu

L’impact SEO des en-têtes de sécurité

Google ne classe pas directement les sites selon leurs en-têtes de sécurité. Cependant, l’impact indirect est significatif :

  • HTTPS est un facteur de ranking : HSTS renforce cette assise
  • La confiance utilisateur : un site sécurisé améliore le taux de rebond et le temps passé sur page
  • Core Web Vitals : une CSP bien configurée peut légèrement améliorer le temps de chargement en bloquant les ressources non autorisées
  • Chrome et les avertissements : les navigateurs signalent de plus en plus les sites aux pratiques de sécurité insuffisantes

Investir dans la sécurité de vos en-têtes HTTP participe donc à une stratégie SEO globale et pérenne.

Conclusion : sécurisez votre site dès maintenant

Configurer la Content Security Policy et les en-têtes de sécurité HTTP n’est plus une option en 2024 — c’est une nécessité. Les attaques XSS et les injections de contenu restent parmi les menaces les plus courantes, et une CSP correctement déployée constitue votre meilleure ligne de défense.

Retenez les étapes essentielles :

  1. Inventoriez toutes les ressources tierces de votre site
  2. Rédigez une politique stricte avec default-src 'self' comme base
  3. Testez en mode Report-Only pendant au moins deux semaines
  4. Déployez progressivement en production
  5. Monitorez les violations en continu
  6. Complétez avec les en-têtes HSTS, X-Content-Type-Options, Referrer-Policy et Permissions-Policy

La mise en place d’une CSP robuste demande une expertise technique pointue, en particulier sur des plateformes complexes comme PrestaShop ou WordPress avec de nombreux plugins. Si vous souhaitez sécuriser votre site web sans risquer de casser vos fonctionnalités existantes, les experts de Lueur Externe vous accompagnent dans l’audit, la configuration et le monitoring de vos en-têtes de sécurité. Contactez-nous pour un diagnostic de sécurité complet de votre site.