CSP für Netlify konfigurieren
Schritt-für-Schritt-Anleitung: Content Security Policy auf Netlify einrichten, mit _headers für statische Sites und Edge Functions für dynamische Nonces.
Content Security Policy auf Netlify
Content Security Policy (CSP) ist der wichtigste HTTP-Security-Header gegen Cross-Site Scripting (XSS). Er teilt dem Browser mit, welche Ressourcen geladen werden dürfen — und blockiert alles andere. CSP ist mit 35 von 166 Punkten der einflussreichste Header im Wolf-Agents Web Security Check.
Auf Netlify setzen Sie CSP per _headers-Datei oder netlify.toml für statische Policies. Für dynamische Nonces nutzen Sie Edge Functions (Deno-Runtime), die pro Request einen einzigartigen Nonce generieren und in Script-Tags einfügen.
CSP im Report-Only-Modus setzen
Beginnen Sie immer im Report-Only-Modus. Der Browser meldet CSP-Verstoße in der Konsole, blockiert aber keine Ressourcen. So identifizieren Sie fehlende Quellen, bevor Sie blockieren.
# _headers — CSP Report-Only
/*
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none' # netlify.toml — CSP Report-Only
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy-Report-Only = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" Verwenden Sie nicht beide für denselben Header. netlify.toml hat Vorrang und überschreibt _headers. Entscheiden Sie sich für einen Weg pro Header.
Violations analysieren und CSP anpassen
Öffnen Sie die Browser DevTools (F12) und die Console. CSP-Violations erscheinen als Warnungen. Passen Sie die Policy an, bis keine unerwarteten Violations mehr auftreten.
| Violation | Lösung |
|---|---|
| Google Analytics blockiert | *.google-analytics.com *.googletagmanager.com in script-src und connect-src |
| Google Fonts blockiert | fonts.googleapis.com in style-src, fonts.gstatic.com in font-src |
| Inline-Script blockiert | Nonce per Edge Function oder Script in externe Datei auslagern |
| YouTube/Vimeo blockiert | *.youtube.com *.vimeo.com in frame-src |
| Netlify Forms blockiert | https://app.netlify.com in form-action hinzufügen |
deploy-preview-*.netlify.app, was zusätzliche CSP-Anpassungen erfordern kann. Enforcement aktivieren
Wenn keine unerwarteten Violations mehr auftreten, wechseln Sie von Content-Security-Policy-Report-Only zu Content-Security-Policy. Der Browser blockiert ab sofort nicht autorisierte Ressourcen.
# netlify.toml — CSP Enforcement
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" Dynamische Nonces per Edge Function
Für maximale Sicherheit generieren Sie CSP-Nonces pro Request über eine Edge Function. Die Funktion liest die HTML-Response, fügt Nonce-Attribute in Script-Tags ein und setzt den CSP-Header mit dem passenden Nonce.
// netlify/edge-functions/csp-nonce.ts
import type { Context } from "https://edge.netlify.com";
export default async (request: Request, context: Context) => {
const response = await context.next();
const contentType = response.headers.get("content-type") || "";
// Nur HTML-Responses verarbeiten
if (!contentType.includes("text/html")) {
return response;
}
// Nonce generieren
const nonce = crypto.randomUUID().replace(/-/g, "");
// HTML lesen und Nonce in Script-Tags einfügen
let html = await response.text();
html = html.replace(
/<script(?![^>]*nonce)/g,
`<script nonce="${nonce}"`
);
// CSP-Header mit Nonce setzen
const csp = [
"default-src 'self'",
`script-src 'self' 'nonce-${nonce}'`,
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data:",
"font-src 'self'",
"object-src 'none'",
"base-uri 'self'",
"form-action 'self'",
"frame-ancestors 'none'",
].join("; ");
return new Response(html, {
status: response.status,
headers: {
...Object.fromEntries(response.headers),
"Content-Security-Policy": csp,
"Content-Type": "text/html; charset=utf-8",
},
});
};
export const config = { path: "/*" }; Wenn Sie CSP per Edge Function setzen, überschreibt dies den CSP-Header aus netlify.toml oder _headers. Entfernen Sie den statischen CSP aus netlify.toml, um Konflikte zu vermeiden.
Häufige Fehler bei CSP auf Netlify
Doppelter CSP-Header
netlify.toml und Edge Function setzen beide CSP. Browser wenden beide Policies an (Intersection). Entfernen Sie den statischen CSP, wenn Sie Edge Functions nutzen.
Nonces und CDN-Cache
Edge Functions laufen vor dem CDN-Cache. Wenn Netlify eine gecachte Response liefert, wird die Edge Function trotzdem ausgeführt — Nonces sind daher sicher.
Deploy Preview mit anderem CSP
Deploy Previews unter deploy-preview-*.netlify.app erhalten denselben CSP. Wenn Ihr CSP spezifische Domains erlaubt, beachten Sie die Preview-Domain.
Netlify Forms und CSP
Netlify Forms sendet Daten an app.netlify.com. Fügen Sie diese Domain in form-action hinzu, wenn Sie Netlify Forms nutzen.
Compliance-Relevanz
PCI DSS 4.0 (Anforderung 6.4.3) fordert ab März 2025 die Kontrolle aller auf Zahlungsseiten geladenen Scripts. Eine korrekte Content Security Policy erfüllt diese Anforderung. NIS2 verlangt technische Maßnahmen zur Cybersicherheit — CSP ist der wirksamste Schutz gegen XSS-Angriffe. Der Wolf-Agents Web Security Check bewertet CSP mit bis zu 35 Punkten und dokumentiert den Umsetzungsstand.
Wie steht Ihre Domain bei Content Security Policy?
Prüfen Sie es jetzt — kostenlos, ohne Registrierung, mit 166 Prüfpunkte.