Zum Inhalt
Website-Checkvon pandaworks

← Alle Punkte · Sicherheit

Content-Security-Policy

Was geprüft

Gelesen wird die Content-Security-Policy (CSP, Regeln dafür, woher die Seite Skripte und andere Inhalte laden darf) aus den Kopfzeilen und aus <meta http-equiv>; ausgewertet werden beide wie im Browser gemeinsam. Bewertet werden fehlende Einschränkung von Skripten (weder script-src noch default-src), 'unsafe-inline' ohne Nonce, Hash oder 'strict-dynamic', Platzhalterquellen wie * oder https: sowie fehlendes object-src und base-uri. Eine Schwäche zählt nur, wenn keine der erzwungenen Policies sie schließt.

Wie relevant

Mittel, wenn keine CSP gesetzt ist oder sie Skripte nicht wirksam einschränkt. Niedrig, wenn nur eine Report-Only-Policy gesetzt ist (ein üblicher Zwischenschritt) oder nur object-src beziehungsweise base-uri fehlen. Nicht höher als Mittel, weil eine CSP eine zusätzliche Schutzschicht ist, die erst bei einer anderen Lücke wirkt.

Warum

Gelingt es jemandem, fremden Code in die Seite einzuschleusen, etwa über ein verwundbares Plugin oder ein Formularfeld, verhindert eine wirksame CSP, dass dieser Code ausgeführt wird oder Daten an fremde Server sendet. Ohne CSP führt der Browser jedes eingeschleuste Skript aus. Erlaubt die CSP 'unsafe-inline', sperrt sie zwar Skripte von nicht genannten Servern, führt aber direkt in die Seite eingeschleusten Code weiterhin aus.

Wie beheben

Der Weg hängt davon ab, was unter „Was gefunden“ steht. Fehlt die CSP oder gibt es nur eine Report-Only-Policy: Beginnen Sie mit der Report-Only-Startvorlage unten. Sie blockiert nichts, sondern meldet Verstöße in der Browserkonsole. Rufen Sie alle Seitentypen auf (Formulare, Karten, Videos, Einwilligungsbanner, Kasse), ergänzen Sie die nötigen Quellen und schalten Sie erst danach von Content-Security-Policy-Report-Only auf Content-Security-Policy um. Ist die CSP gesetzt und erlaubt 'unsafe-inline': Lagern Sie direkt in die Seite geschriebene Skripte in Dateien aus oder geben Sie jedes einzeln per Nonce oder Hash frei, und entfernen Sie 'unsafe-inline' erst danach, wieder zuerst als Report-Only. Fehlen nur object-src oder base-uri: Ergänzen Sie object-src 'none' und base-uri 'self'; das ist auch neben 'unsafe-inline' sinnvoll.

Nebenwirkung: Eine zu strenge erzwungene CSP bricht Skripte, Formulare, Karten und Einwilligungsbanner ohne sichtbare Fehlermeldung. Deshalb immer zuerst Report-Only und mehrere Tage beobachten. Praxishinweis: Mit Cloudflare Turnstile braucht die CSP die Quelle challenges.cloudflare.com in script-src und frame-src, sonst scheitern Formulare lautlos; mit Google Fonts gehören fonts.googleapis.com in style-src und fonts.gstatic.com in font-src.

WordPress: Seitenbaukästen, Einwilligungs- und Statistik-Plugins setzen oft Inline-Skripte; eine strenge CSP ohne 'unsafe-inline' ist dann nur mit Nonces möglich, die bei Seiten-Caching nicht pro Abruf wechseln. Vorsicht bei Lösungen, die jedem Skript der fertigen Seite nachträglich eine Nonce geben: Ein eingeschleustes Skript bekäme sie dann ebenfalls, die CSP wirkt nur noch auf dem Papier. Realistisches Ziel ist bei solchen Seiten oft eine CSP mit eingeschränkten Quellen, object-src 'none' und base-uri 'self'. Sicherheits- und Cache-Plugins schreiben die .htaccess oft selbst um und können eigene Kopfzeilen dabei entfernen oder doppelt setzen. Setzen Sie Kopfzeilen deshalb an genau einer Stelle (Plugin oder .htaccess außerhalb der Plugin-Blöcke „# BEGIN … # END“) und prüfen Sie nach jedem Plugin-Update mit curl -I.

Codebeispiel

Apache (.htaccess) — Report-Only-Startvorlage

<IfModule mod_headers.c>
    Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'"
</IfModule>

nginx — Report-Only-Startvorlage

add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'" always;

Cloudflare (Transform Rule)

Rules → Transform Rules → Response Header Transform Rules → Regel anlegen
Bedingung: Hostname gleich beispiel.de
Aktion: Set static
  Header: Content-Security-Policy-Report-Only
  Wert:   default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
Nach der Beobachtungsphase den Kopfzeilennamen auf Content-Security-Policy ändern.

Weiterführende Quellen

Quellen der Methodik

  • docs/SCORING.md — Status und Schweregrade (§2), Kategoriescore und Abdeckung (§3), Gesamtwert (§4), keine Doppelabzüge (§5), Prüfkatalog mit Gewichten (§6), Versionierung (§8), Formulierungsregeln (§9), bewusst nicht geprüft (§10)
  • docs/KALIBRIERUNG.md — Abgleich der Schwerefaktoren und Kappen mit externen Ankern (Web Almanac, Lighthouse, MDN HTTP Observatory, SSL Labs), Entscheidung scoring@1.4.0