CSP ist eine der effektivsten Verteidigungen gegen XSS-Angriffe. Durch die Kontrolle, welche Ressourcen geladen werden dürfen, kann CSP böswillige Code-Injektion verhindern.
Was ist CSP?
CSP ist ein HTTP-Response-Header, der kontrolliert, welche Ressourcen der Browser laden darf.
Wie CSP funktioniert
Der Browser blockiert Ressourcen, die gegen die Richtlinie verstoßen:
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)Alle CSP-Direktiven
| Direktive | Steuert | Beispiel |
|---|---|---|
| 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) |
Quellwerte erklärt
| Quelle | Bedeutung |
|---|---|
| '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 |
Schrittweise Implementierung
Schritt 1: Report-Only-Modus
Zuerst im Report-Only-Modus bereitstellen:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-reportSchritt 3: Richtlinie erstellen
Richtlinie basierend auf Ergebnissen:
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-requestsHäufige Konfigurationen
Strenge Richtlinie
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-requestsModerat (typische SPA)
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'Mit 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.comImplementierungsmethoden
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();
});HTML Meta Tag
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'">Häufige Fehler
| Fehler | Auswirkung | Lösung |
|---|---|---|
| unsafe-inline für Skripte | XSS-Schutz aufgehoben | Nonces oder Hashes verwenden |
| unsafe-eval | Erlaubt eval() | Code ohne eval() refaktorieren |
| Wildcard in script-src | Skripte von allen Domains | Spezifische Domains whitelisten |
| Inline-Styles vergessen | Blockiert CSS-in-JS | unsafe-inline oder Nonces für style-src |
| Kein Report-Only-Test | Site-Funktionalität bricht | Immer mit Report-Only starten |
| base-uri fehlt | Base-Tag-Injection möglich | base-uri 'self' hinzufügen |
FAQ
Welche Angriffe verhindert CSP?
Hauptsächlich XSS. Auch Clickjacking und Dateninjection.
Ersetzt CSP Input-Validierung?
Nein. CSP ist Defense-in-Depth.
CSP mit Inline-Skripten?
Nonces oder Hashes verwenden. unsafe-inline vermeiden.
Verlangsamt CSP die Website?
Nein. Der Performance-Einfluss ist vernachlässigbar.