Politique de sécurité du contenu Écrire une en-tête de CSP qui fonctionne vraiment
La plupart des développeurs savent qu'ils devraient ajouter une politique de sécurité du contenu (CSP) à leurs applications. Peu en ont une qui fonctionne vraiment. Soit elle est trop permissive et annule son objectif, soit elle casse la moitié du site et est supprimée par frustration.
Ce guide explique ce que fait la CSP, quels directives sont importants, et comment écrire une directive qui empêche de véritables attaques sans endommager votre application.
Ce que fait vraiment la CSP
Une politique de sécurité du contenu indique au navigateur d'où il est autorisé à charger des ressources. Des scripts de ce domaine uniquement. Des styles depuis ce CDN. Des images depuis n'importe où. Aucun script en ligne.
Quand un navigateur reçoit une politique de sécurité du contenu (CSP), il applique ces règles avant d'exécuter quoi que ce soit. Si une attaque par injection de scripts (XSS) injecte un script malveillant dans votre HTML, la CSP l'empêche au niveau du navigateur — même si le script a pu passer votre nettoyage des entrées.
C'est la valeur fondamentale : la CSP est votre deuxième ligne de défense lorsque la validation des entrées échoue.
Les directives qui comptent
La CSP dispose de dizaines de directives, mais la plupart des en-têtes de production n'en ont besoin que six :
| Directive | Ce qu'elle limite | Erreur courante |
|---|---|---|
default-src |
Fonctionnement par défaut pour tout type de ressource non explicitement listé | Paramètre 'self', puis oublier que les polices et les cadres ne sont pas couverts |
script-src |
Les URLs de sources JavaScript et l'exécution en ligne | Ajouter 'unsafe-inline' pour silencier les erreurs dans la console |
style-src |
Les URLs de sources CSS et les blocs de styles en ligne | Oublier votre CDN ou les styles en ligne injectés par des bibliothèques JavaScript |
img-src |
Les sources d'images, y compris les URI de données | Manquant data: pour les images en base64, blob: pour les exports de canvas |
connect-src |
Les destinations de XHR, fetch, WebSocket et EventSource | Oublier les points de terminaison d'analytiques et les sous-domaines d'API |
frame-ancestors |
Les origines pouvant intégrer votre site dans un <iframe> |
L'omission complète — laisser le clickjacking ouvert |
frame-ancestors remplace l'ancienne X-Frame-Options en-tête et mérite d'être ajoutée même avant d'avoir une couverture complète de la CSP ailleurs.
Pourquoi unsafe-inline Destruction de l'objectif
Quand vous ajoutez 'unsafe-inline' à script-src, vous dites au navigateur : exécutez tout script que vous trouvez, quelle que soit son origine. Cela inclut les scripts injectés par des attaques XSS.
'unsafe-eval' est pire — elle permet eval(), Function()et setTimeout("string"), qui sont des vecteurs d'attaque courants même dans des bases de code apparemment propres.
Une politique incluant l'un de ces documents affiche vos sources sans offrir la moindre protection contre l'injection. L'attaquant n'a pas besoin de savoir d'où vos scripts légitimes sont chargés s'il peut injecter ses propres scripts en ligne.
La méthode correcte : les nonces et les hachages
Si vous avez des scripts en ligne légitimes, vous avez deux options qui ne compromettent pas votre politique :
Les nonces génèrent un token unique par chargement de page. Le serveur l'ajoute à l'en-tête CSP et à l'attribut nonce du script en ligne. Seuls les scripts avec un nonce correspondant sont exécutés.
<!-- CSP header -->
Content-Security-Policy: script-src 'nonce-abc123xyz'
<!-- Inline script with matching nonce -->
<script nonce="abc123xyz">
window.analyticsId = '...';
</script>
Les hachages calculent un hachage SHA-256 de contenu exact du script. Ajoutez ce hachage à script-src et le navigateur exécute uniquement ce script spécifique — rien d'autre.
Content-Security-Policy: script-src 'sha256-RFWPLDbv2BY+rCkDzsE+0fr8ylGr2R2faWMhq4lfEQc='
Les nonces fonctionnent mieux pour des pages dynamiques où le contenu change à chaque requête. Les hachages conviennent aux scripts statiques qui ne changent pas entre les déploiements.
Déployer avec le mode rapport uniquement en premier
Ajouter la CSP à un site existant sans test est la manière dont on la casse en production. Commencez par l'en-tête de rapport uniquement :
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'nonce-{random}'; report-uri /csp-violations
Le navigateur applique les règles et enregistre les violations — rien n'est bloqué pour l'instant. Ce journal de violations vous indique exactement ce que vous devez ajouter à la politique avant de la passer en mode de mise en œuvre.
La plupart des déploiements CSP qui cassent des sites ont omis cette étape.
Une vraie CSP pour une application SaaS typique
Voici un en-tête de production prêt à l'emploi pour une application utilisant un CDN, Google Analytics et Stripe. Chaque directive est annotée :
Content-Security-Policy:
# Tight default: only load from your own origin
default-src 'self';
# Scripts: your origin, GA tag manager via nonce, Stripe.js
script-src 'self' https://www.googletagmanager.com https://js.stripe.com 'nonce-{SERVER_NONCE}';
# Styles: your origin and Google Fonts CSS
style-src 'self' https://fonts.googleapis.com;
# Fonts: your origin and Google Fonts CDN
font-src 'self' https://fonts.gstatic.com;
# Images: your origin, CDN subdomain, and base64 data URIs
img-src 'self' https://cdn.yourdomain.com data:;
# Fetch/XHR: your API, GA collection endpoint, Stripe API
connect-src 'self' https://www.google-analytics.com https://api.stripe.com;
# Stripe renders its fields in an iframe
frame-src https://js.stripe.com;
# Nobody should be framing your app
frame-ancestors 'none';
# Block <object> and <embed> entirely
object-src 'none';
# Force HTTP requests to upgrade to HTTPS
upgrade-insecure-requests;
Remplacez {SERVER_NONCE} avec une valeur aléatoire cryptographiquement sécurisée générée par requête — par exemple, base64_encode(random_bytes(16)) en PHP ou crypto.randomBytes(16).toString('base64') en Node.
Erreurs CSP courantes
Des étoiles trop larges. script-src * autorise les scripts d'origines quelconques. Vous pourriez dire que vous n'avez pas de politique de scripts du tout.
Oublier les sous-domaines. 'self' ne couvre que votre origine exacte. https://api.yourdomain.com est une origine différente et nécessite une entrée explicite sous connect-src.
Omettre frame-ancestors. La protection contre le clickjacking est indépendante de la protection contre les XSS. Ajoutez-la séparément de l'ensemble des directives.
Configurer la CSP dans plusieurs endroits. Si votre CDN et votre application définissent tous deux un en-tête CSP, le comportement devient imprévisible. Définissez-le dans une seule couche — généralement votre serveur d'origine ou votre reverse proxy.
L'utilisation de report-uri sans un gestionnaire. Les violations génèrent des requêtes POST vers votre point de terminaison à chaque chargement de page affecté. Soit vous les gérez, soit vous les envoyez vers un service comme Report URI.
Construire votre en-tête sans la peine
Suivre chaque domaine que votre page charge via des scripts, des styles, des polices, des images et des appels API devient vite fastidieux. Un générateur en ligne d'en-tête CSP vous permet de configurer chaque directive de manière visuelle et de produire un en-tête prêt à l'emploi que vous pouvez coller directement dans votre configuration serveur.
Utilisez-le comme point de départ, puis vérifiez vos requêtes réelles dans DevTools pour capturer tout ce que le générateur a omis.
Une CSP trop large est une simple décoration. Une CSP trop stricte casse l'expérience utilisateur. Commencez en mode rapport uniquement, affinez progressivement, et utilisez les nonces lorsque des scripts en ligne sont inévitables. Votre politique doit rendre la tâche des attaquants plus difficile — pas la vôtre.
Vous aimerez peut-être aussi
Installez nos extensions
Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide
恵 Le Tableau de Bord Est Arrivé !
Tableau de Bord est une façon amusante de suivre vos jeux, toutes les données sont stockées dans votre navigateur. D'autres fonctionnalités arrivent bientôt !
Outils essentiels
Tout voir Nouveautés
Tout voirMise à jour: Notre dernier outil was added on Mai 21, 2026
