CSP für Astro konfigurieren
Schritt-für-Schritt-Anleitung: Content Security Policy in Astro per Middleware mit Nonces einrichten -- von Report-Only bis Enforcement, inklusive Islands-Kompatibilität.
Content Security Policy in Astro
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.
In Astro setzen Sie CSP per Middleware (src/middleware.ts) im SSR-Modus. Die Middleware generiert einen Nonce per crypto.randomUUID() und teilt ihn über context.locals.nonce mit Templates. Astro Islands (React, Vue, Svelte) benötigen 'strict-dynamic' in der CSP, damit Hydration-Scripts korrekt ausgeführt werden.
CSP-Middleware im Report-Only-Modus
Beginnen Sie immer im Report-Only-Modus. Astro meldet CSP-Verstoße in der Browser-Konsole, blockiert aber keine Ressourcen. Der Nonce wird per crypto.randomUUID() erzeugt und über context.locals an Templates weitergegeben.
// src/middleware.ts -- CSP Report-Only
import { defineMiddleware } from 'astro:middleware';
import crypto from 'node:crypto';
export const onRequest = defineMiddleware(async (context, next) => {
const nonce = crypto.randomUUID();
context.locals.nonce = nonce;
const response = await next();
response.headers.set(
'Content-Security-Policy-Report-Only',
[
"default-src 'self'",
`script-src 'self' 'nonce-${nonce}' 'strict-dynamic'`,
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data:",
"font-src 'self'",
"connect-src 'self'",
"object-src 'none'",
"base-uri 'self'",
"form-action 'self'",
"frame-ancestors 'none'",
].join('; ')
);
return response;
}); 'strict-dynamic'? Astro Islands laden Hydration-Scripts dynamisch. 'strict-dynamic' erlaubt Scripts, die von einem Nonce-autorisierten Script geladen werden -- ohne jedes einzelne Script explizit in der CSP aufzulisten. Wolf-Agents nutzt dieses Muster produktiv.
Violations analysieren und CSP anpassen
Öffnen Sie die Browser DevTools (F12) und die Console. CSP-Violations erscheinen als Warnungen mit der blockierten Ressource und der verletzten Direktive. Passen Sie die CSP-Konfiguration in der Middleware an, bis keine unerwarteten Violations mehr auftreten.
| Violation | Lösung in der Middleware |
|---|---|
| Island-Hydration blockiert | 'strict-dynamic' in script-src + Nonce im Layout |
| Google Fonts blockiert | fonts.googleapis.com in style-src, fonts.gstatic.com in font-src |
| API-Calls blockiert | API-Domain zu connect-src hinzufügen |
| Analytics blockiert | Analytics-Domain zu script-src und connect-src |
| iframe-Einbettung blockiert | *.youtube.com in frame-src hinzufügen |
Enforcement aktivieren
Wenn keine unerwarteten Violations mehr auftreten, ändern Sie den Header-Namen von Content-Security-Policy-Report-Only zu Content-Security-Policy. Der Browser blockiert ab sofort nicht autorisierte Ressourcen.
// src/middleware.ts -- CSP Enforcement
import { defineMiddleware } from 'astro:middleware';
import crypto from 'node:crypto';
export const onRequest = defineMiddleware(async (context, next) => {
const nonce = crypto.randomUUID();
context.locals.nonce = nonce;
const response = await next();
response.headers.set(
'Content-Security-Policy',
[
"default-src 'self'",
`script-src 'self' 'nonce-${nonce}' 'strict-dynamic'`,
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data:",
"font-src 'self'",
"connect-src 'self'",
"object-src 'none'",
"base-uri 'self'",
"form-action 'self'",
"frame-ancestors 'none'",
].join('; ')
);
return response;
}); # Nginx -- statische CSP ohne Nonces (SSG-Fallback)
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always; Nonces in Templates und Islands
Im SSR-Modus ist der Nonce über Astro.locals.nonce in jedem .astro-Template verfügbar. Für Inline-Scripts setzen Sie das nonce-Attribut explizit. Islands-Hydration funktioniert über 'strict-dynamic' automatisch.
<!-- src/layouts/Layout.astro -- Nonce in Templates -->
---
const { nonce } = Astro.locals;
---
<html>
<head>
<!-- Inline-Script mit Nonce -->
<script nonce={nonce}>
console.log('Autorisiertes Script');
</script>
</head>
<body>
<slot />
<!-- Island-Komponente: React -->
<!-- strict-dynamic erlaubt von Nonce-Scripts geladene Scripts -->
<MyReactComponent client:load />
</body>
</html> # Production-Build und CSP-Header prüfen
npm run build && node dist/server/entry.mjs
curl -sI https://ihre-domain.de | grep -i content-security
# Erwartete Ausgabe:
# Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123...' 'strict-dynamic'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none' Häufige Fehler bei CSP in Astro
Middleware laeuft nicht für prerenderte Seiten
Seiten mit export const prerender = true werden zur Build-Zeit gerendert. Die Middleware wird nicht ausgeführt -- CSP-Nonces fehlen. Setzen Sie CSP für prerenderte Seiten auf dem Webserver.
Islands-Hydration ohne strict-dynamic
Ohne 'strict-dynamic' blockiert die CSP Hydration-Scripts von Islands (React, Vue, Svelte). Diese werden dynamisch eingefuegt und haben keinen eigenen Nonce.
SSG-Build hat keine Server-CSP
output: 'static' generiert nur HTML-Dateien. Es gibt keinen Server und keine Middleware. CSP muss auf dem Hosting (Vercel, Netlify) oder Webserver konfiguriert werden -- ohne Nonces.
Nonce wird nicht im Template genutzt
Der Nonce in der Middleware allein genuegt nicht. Jedes <script>-Tag in .astro-Dateien braucht nonce={Astro.locals.nonce} -- sonst blockiert die CSP das Script trotz gesetztem Header.
Compliance-Relevanz
PCI DSS 4.0 (Anforderung 6.4.3) fordert ab März 2025 die Kontrolle aller auf Zahlungsseiten geladenen Scripts -- eine Nonce-basierte CSP 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.