Le CSP est l'une des défenses les plus efficaces contre les attaques XSS. En indiquant au navigateur quelles ressources peuvent être chargées, le CSP prévient l'injection de code malveillant.
Qu'est-ce que le CSP ?
Le CSP est un en-tête HTTP qui contrôle les ressources que le navigateur peut charger.
Comment fonctionne le CSP
Le navigateur bloque les ressources qui violent la politique :
Browser receives HTTP response:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
Browser allows:
✅ <script src="/app.js"> (same origin = 'self')
✅ <script src="https://cdn.example.com/lib.js">
Browser blocks:
❌ <script src="https://evil.com/steal.js">
❌ <script>alert('XSS')</script> (inline = not allowed)Toutes les directives CSP
| Directive | Contrôle | Exemple |
|---|---|---|
| default-src | Fallback for all resource types | 'self' |
| script-src | JavaScript files and inline scripts | 'self' https://cdn.example.com |
| style-src | CSS stylesheets and inline styles | 'self' 'unsafe-inline' |
| img-src | Images (img, favicon, CSS background) | 'self' data: https: |
| font-src | Web fonts (@font-face) | 'self' https://fonts.gstatic.com |
| connect-src | XHR, fetch, WebSocket, EventSource | 'self' https://api.example.com |
| media-src | Audio and video elements | 'self' |
| frame-src | Iframes and embedded frames | 'self' https://www.youtube.com |
| object-src | Plugins (Flash, Java applets) | 'none' |
| base-uri | Base element URLs | 'self' |
| form-action | Form submission targets | 'self' |
| frame-ancestors | Who can embed this page (anti-clickjacking) | 'self' |
| upgrade-insecure-requests | Upgrade HTTP requests to HTTPS | (no value needed) |
Valeurs sources
| Source | Signification |
|---|---|
| 'self' | Same origin (protocol + host + port) |
| 'none' | Block all resources of this type |
| 'unsafe-inline' | Allow inline scripts/styles (reduces security!) |
| 'unsafe-eval' | Allow eval(), Function(), setTimeout(string) |
| 'strict-dynamic' | Trust scripts loaded by already-trusted scripts |
| 'nonce-abc123' | Allow specific inline script with matching nonce attribute |
| 'sha256-...' | Allow inline script matching this hash |
| https: | Allow any HTTPS resource |
| data: | Allow data: URIs (e.g., inline images) |
| blob: | Allow blob: URIs |
| *.example.com | Allow all subdomains of example.com |
Implémentation étape par étape
Étape 1 : Mode rapport uniquement
Déployer d'abord en mode rapport :
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-reportÉtape 3 : Construire la politique
Créer la politique :
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.example.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.example.com;
frame-ancestors 'self';
base-uri 'self';
form-action 'self';
object-src 'none';
upgrade-insecure-requestsConfigurations courantes
Politique stricte
Content-Security-Policy:
default-src 'none';
script-src 'self';
style-src 'self';
img-src 'self';
font-src 'self';
connect-src 'self';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
object-src 'none';
upgrade-insecure-requestsModérée (SPA typique)
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.example.com wss://ws.example.com;
frame-ancestors 'self'Avec Google Analytics
Content-Security-Policy:
default-src 'self';
script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com;
img-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;
connect-src 'self' https://www.google-analytics.com https://analytics.google.comMéthodes d'implémentation
Nginx
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;Apache
Header set Content-Security-Policy "default-src 'self'; script-src 'self'"Express.js
// Using helmet middleware (recommended)
const helmet = require('helmet');
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
}
}));
// Or manually
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',
"default-src 'self'; script-src 'self'");
next();
});Balise Meta HTML
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'">Erreurs courantes
| Erreur | Impact | Solution |
|---|---|---|
| unsafe-inline pour les scripts | Protection XSS désactivée | Utiliser nonces ou hashes |
| unsafe-eval | Permet eval() | Refactorer sans eval() |
| Wildcard dans script-src | Scripts de n'importe quel domaine | Lister les domaines spécifiques |
| Oublier les styles inline | Bloque CSS-in-JS | Ajouter unsafe-inline à style-src |
| Ne pas tester en report-only | Casse le site | Toujours commencer en report-only |
| base-uri manquant | Injection de balise base | Ajouter base-uri 'self' |
FAQ
Quelles attaques le CSP prévient-il ?
Principalement les attaques XSS. Aussi le clickjacking et l'injection de données.
Le CSP remplace-t-il la validation d'entrée ?
Non. C'est une défense en profondeur.
Comment utiliser le CSP avec des scripts inline ?
Utiliser des nonces ou des hashes. Éviter unsafe-inline.
Le CSP ralentit-il le site ?
Non. L'impact sur les performances est négligeable.