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.

Astro · Schritt für Schritt

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.

1 Schritt 1 von 4

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 Report-Only
// 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;
});
Warum '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.

2 Schritt 2 von 4

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
3 Schritt 3 von 4

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 Produktiv
// 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;
});
Testen Sie gruendlich auf allen Seiten -- inklusive Formulare, Dashboard und dynamische Islands. Jede nicht getestete Seite kann nach dem Wechsel zu Enforcement unerwartete Blockierungen aufweisen.
nginx.conf SSG-Fallback
# 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;
4 Schritt 4 von 4

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 Nonces
<!-- 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>
Terminal Verifizieren
# 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.