Leitfaden
Content Security Policy und Security-Header richtig einrichten
Eine Content Security Policy (CSP) ist ein HTTP-Header, mit dem Ihre Website dem Browser vorschreibt, aus welchen Quellen er Skripte, Styles, Bilder und Frames laden darf. Richtig eingerichtet verhindert sie, dass eingeschleustes JavaScript ausgeführt wird. Zusammen mit vier weiteren Headern, nämlich Strict-Transport-Security, X-Content-Type-Options, Referrer-Policy und Permissions-Policy, bildet sie die Grundausstattung, die jede Website auf jeder Antwort ausliefern sollte, nicht nur auf der Startseite.
- Die CSP schützt nur, wenn
script-srcohne'unsafe-inline'auskommt. Inline-Skripte erlauben Sie stattdessen per Hash oder Nonce. - Klickjacking verhindern Sie mit
frame-ancestorsin der CSP.X-Frame-Optionsbleibt höchstens als Rückfall für ältere Browser,X-XSS-Protectionsetzen Sie gar nicht mehr. - Einige Funktionen gibt es nur im HTTP-Header:
frame-ancestorsund der Report-Only-Modus wirken nicht in einem Meta-Tag. - Messen Sie per GET auf mehreren URLs, auch auf Fehlerseiten. Starten Sie eine neue CSP im Report-Only-Modus und schalten Sie erst scharf, wenn die Konsole sauber ist.
Die Header im Überblick
Was jeder Header tut und welcher Wert passt.
Zum AbschnittCSP aufbauen
Direktiven, Hashes, Nonces, frame-ancestors.
Zum AbschnittUnser eigenes Beispiel
Die gemessenen Header von cybersec42.com.
Zum AbschnittKonfiguration
Vercel, Netlify, Apache und nginx.
Zum AbschnittSecurity-Header prüfen
GET statt HEAD, Konsole, Report-Only.
Zum AbschnittHäufige Fehler
Von unsafe-inline bis Header nur auf der Startseite.
Zum AbschnittDie Security-Header im Überblick
Security-Header sind Anweisungen, die Ihr Server mit jeder Antwort an den Browser schickt. Sie ändern nichts an Ihrem Code, sie schränken nur ein, was der Browser mit Ihrer Seite tun darf. Das ist ihre Stärke und ihre Grenze: Sie mildern ganze Fehlerklassen ab, etwa eingeschleuste Skripte oder das Einbetten Ihrer Seite in einen fremden Frame, beheben aber keine Lücke in der Anwendung selbst.
| Header | Wofür | Üblicher Startwert |
|---|---|---|
Content-Security-Policy | Erlaubte Quellen für Skripte, Styles, Bilder, Verbindungen und Frames; Schutz gegen eingeschleustes JavaScript und Klickjacking | individuell, siehe unten |
Strict-Transport-Security | Browser ruft die Domain nur noch per HTTPS auf (HSTS) | max-age=31536000; includeSubDomains |
X-Content-Type-Options | Browser rät keinen Dateityp, wenn der angegebene nicht passt | nosniff |
Referrer-Policy | Wie viel der eigenen URL an andere Seiten weitergegeben wird | strict-origin-when-cross-origin |
Permissions-Policy | Browser-Funktionen wie Kamera, Mikrofon oder Standort abschalten | geolocation=(), microphone=(), camera=() |
Die Werte in der Tabelle entsprechen den Empfehlungen im OWASP HTTP Headers Cheat Sheet, bei HSTS mit einem Jahr statt der dort genannten zwei Jahre und ohne preload als vorsichtigerem Einstieg. Die einzelnen Header im Detail:
Strict-Transport-Security (HSTS)
HSTS ist in RFC 6797 festgelegt. max-age gibt in Sekunden an, wie lange der Browser Ihre Domain nur noch per HTTPS anspricht. includeSubDomains dehnt das auf alle Subdomains aus. Setzen Sie das erst, wenn wirklich jede Subdomain ein gültiges Zertifikat hat, denn bei einem Zertifikatsfehler auf einem HSTS-Host bietet der Browser laut MDN keine Möglichkeit mehr, trotzdem weiterzugehen. Zwei Details aus der RFC: Ein HSTS-Header, der über unverschlüsseltes HTTP ankommt, wird ignoriert. Und max-age=0 hebt die Regel wieder auf, allerdings erst, wenn der Browser die Seite erneut per HTTPS abruft.
Der Zusatz preload steht nicht in der RFC. Er gehört zur Preload-Liste, die über hstspreload.org gepflegt wird und in Browser eingebaut ist. Voraussetzungen dort: max-age von mindestens einem Jahr, includeSubDomains und preload. Die Seite warnt ausdrücklich, dass eine Austragung Monate dauert, bis sie bei den Nutzern ankommt. Tragen Sie Ihre Domain deshalb nur ein, wenn Sie sicher sind.
X-Content-Type-Options
Der einzige Wert ist nosniff. Laut MDN blockiert der Browser dann Stylesheets, die nicht als text/css ausgeliefert werden, und Skripte ohne JavaScript-Dateityp. Voraussetzung ist, dass Ihr Server für alle Dateien den richtigen Content-Type setzt.
Referrer-Policy
strict-origin-when-cross-origin ist laut W3C-Spezifikation und MDN heute der Standard der Browser, wenn nichts gesetzt ist: innerhalb Ihrer Seite die volle URL, an andere HTTPS-Seiten nur die Domain, an HTTP-Seiten gar nichts. OWASP empfiehlt trotzdem, den Wert ausdrücklich zu setzen, statt sich auf Browser-Voreinstellungen zu verlassen. Wer URLs mit Tokens oder Suchbegriffen hat, kann strenger werden, etwa mit no-referrer.
Permissions-Policy
Mit einer leeren Liste () schalten Sie eine Funktion für Ihre Seite und alle eingebetteten Frames ab, mit (self) erlauben Sie sie nur der eigenen Herkunft. Schalten Sie alles ab, was Ihre Seite nicht braucht. MDN führt den Header als noch nicht in allen verbreiteten Browsern verfügbar. Er ist daher eine zusätzliche Schicht, auf die Sie sich nicht allein verlassen sollten.
X-Frame-Options und X-XSS-Protection
X-Frame-Options verhindert, dass Ihre Seite in einem fremden Frame erscheint. Die CSP-Spezifikation (Level 3) hält fest, dass frame-ancestors diesen Header überstimmt. frame-ancestors 'none' entspricht laut MDN X-Frame-Options: DENY, ist aber flexibler, weil Sie einzelne erlaubte Domains angeben können. X-Frame-Options: DENY zusätzlich zu senden schadet nicht und deckt ältere Browser ab.
X-XSS-Protection dagegen lassen Sie weg. MDN führt den Header als veraltet und nicht standardisiert und warnt, dass der Filter in manchen Fällen selbst XSS-Lücken erzeugen konnte. Auch OWASP rät, ihn nicht zu setzen oder ausdrücklich mit 0 abzuschalten und stattdessen auf eine CSP ohne Inline-JavaScript zu setzen.
Die Content Security Policy aufbauen
Eine CSP besteht aus Direktiven, getrennt durch Semikolon. Jede Direktive nennt einen Ressourcentyp und die erlaubten Quellen. default-src gilt für alle Typen, die nicht eigens aufgeführt sind. Ein solider Ausgangspunkt für eine Website ohne fremde Skripte:
Content-Security-Policy:
default-src 'self';
script-src 'self';
style-src 'self';
img-src 'self' data:;
font-src 'self';
connect-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none'
Im Header steht das in einer Zeile, die Umbrüche dienen hier nur der Lesbarkeit. Die wichtigsten Direktiven:
script-srcist der Kern des Schutzes gegen Cross-Site-Scripting (XSS). Steht hier'unsafe-inline', darf jedes Skript im HTML laufen, auch ein eingeschleustes.object-src 'none'undbase-urischließen zwei Umwege, über die sich Skript-Regeln sonst aushebeln lassen. MDN nennt beide als Teil einer strikten CSP.form-actionlegt fest, wohin Formulare senden dürfen.frame-ancestorsregelt, wer Ihre Seite einbetten darf, also den Klickjacking-Schutz.
Inline-Skripte erlauben, ohne unsafe-inline
Viele Seiten brauchen ein paar Inline-Skripte. Statt 'unsafe-inline' erlauben Sie genau diese Skripte, und zwar auf zwei Arten:
- Hash: Sie berechnen den SHA-256-Hash des Skriptinhalts und tragen ihn als
'sha256-…'inscript-srcein. Geeignet für statische Seiten, deren Skripte sich nur beim Bauen ändern. - Nonce: Der Server erzeugt bei jeder Antwort einen neuen Zufallswert, setzt ihn als
'nonce-…'in den Header und als Attributnonce="…"an jedes erlaubte Skript. Geeignet für Seiten, die serverseitig gerendert werden.
MDN nennt beide Wege eine „strikte CSP“ und die empfohlene Methode gegen XSS. Wichtig für die Umstellung: Enthält eine Direktive einen Hash oder eine Nonce, ignorieren Browser laut MDN und CSP-Spezifikation ein dort ebenfalls stehendes 'unsafe-inline'. Den Hash berechnen Sie über den exakten Inhalt zwischen den Script-Tags, Leerzeichen und Zeilenumbrüche zählen mit:
# inline.js enthält exakt den Text zwischen <script> und </script>
openssl dgst -sha256 -binary inline.js | openssl base64 -A
Inline-Event-Handler wie onclick="…" lassen sich auf diese Weise nicht einfach erlauben. Verlagern Sie sie in eine Skriptdatei mit addEventListener. Für Seiten, die viele Skripte nachladen, gibt es 'strict-dynamic': Ein per Hash oder Nonce erlaubtes Skript darf dann weitere Skripte laden. MDN weist darauf hin, dass das die Policy weniger streng macht, wenn diese Skripte Inhalte aus unsicheren Quellen verarbeiten.
So machen wir es auf dieser Seite
Gemessen am 28.10.2026 per GET mit curl -s -D - -o /dev/null https://www.cybersec42.com/, gegengeprüft auf einer zweiten URL mit Cache-Buster. Beide Antworten trugen dieselben Security-Header. Die CSP ist gekürzt, sie enthält 14 Hashes:
content-security-policy: default-src 'self';
script-src 'self' 'sha256-2TkQLINVURTi/RmDX37prpPrw8Zm7dkRfIzOPWxyCG0='
'sha256-3mC/Lyy+nMH9q6flJmQx73Ahi1EFl8by8yb2zwfjzNU=' … (14 Hashes);
style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';
connect-src 'self'; frame-ancestors 'none'; base-uri 'self';
form-action 'self'; object-src 'none'
strict-transport-security: max-age=63072000; includeSubDomains; preload
x-content-type-options: nosniff
x-frame-options: DENY
referrer-policy: strict-origin-when-cross-origin
permissions-policy: geolocation=(), microphone=(), camera=(), interest-cohort=()
Die Seite ist statisch und wird über Vercel ausgeliefert. Die Header stehen in der vercel.json mit "source": "/(.*)", gelten also für jede Datei. Ein kleines Build-Skript sucht vor jedem Deploy alle Inline-Skripte im Bundle, berechnet ihre SHA-256-Hashes und schreibt sie in script-src. Strukturierte Daten in <script type="application/ld+json"> sind reine Datenblöcke, werden nicht ausgeführt und brauchen keinen Hash. Inline-Event-Handler gibt es nicht. Ändert sich ein Inline-Skript, ohne dass das Skript neu läuft, blockiert der Browser es. Genau das wollen wir: Was nicht ausdrücklich erlaubt ist, läuft nicht.
Zwei bewusste Entscheidungen sehen Sie in der Messung. style-src enthält 'unsafe-inline', weil die Seiten Stilangaben im HTML nutzen. Für Styles ist das ein kleineres Restrisiko als für Skripte, aber kein null Risiko, daher steht es auf unserer Liste. Und wir senden X-Frame-Options: DENY zusätzlich zu frame-ancestors 'none', als Rückfall für ältere Browser.
Konfigurationsbeispiele für Vercel, Netlify, Apache und nginx
Die Beispiele setzen dieselben Header wie die Tabelle oben. Die CSP ist der Ausgangspunkt aus dem vorigen Abschnitt, passen Sie sie an Ihre Seite an und testen Sie sie zuerst im Report-Only-Modus.
Vercel: vercel.json
Laut Vercel-Dokumentation legen Sie Header im Feld headers fest, je Pfadmuster unter source. /(.*) trifft alle Pfade.
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Content-Security-Policy", "value": "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" },
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "geolocation=(), microphone=(), camera=()" }
]
}
]
}
Netlify: _headers
Die Datei _headers gehört in das Verzeichnis, das Netlify veröffentlicht, also das Build-Ergebnis. Die Netlify-Dokumentation weist auf eine Grenze hin: Diese Header gelten nur für Dateien, die Netlify selbst ausliefert, nicht für Antworten aus Serverless- oder Edge-Functions und nicht für weitergeleitete Inhalte. Dort muss die Funktion die Header selbst setzen.
/*
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Apache: .htaccess
Apache setzt Header über mod_headers. In einer .htaccess funktioniert das laut Apache-Dokumentation nur mit AllowOverride FileInfo. Verwenden Sie Header always set: Ohne always landen die Header nicht auf Weiterleitungen und Fehlerseiten.
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
nginx
In nginx gilt add_header laut Dokumentation ohne den Zusatz always nur für erfolgreiche Antworten und Weiterleitungen, nicht für Fehlerseiten. Die größere Falle ist die Vererbung: Header aus dem server-Block gelten in einem location-Block nur, wenn dort kein eigenes add_header steht. Ein einzelnes add_header Cache-Control … in einer Location lässt dort alle Security-Header verschwinden. Ab nginx 1.29.3 lässt sich das mit add_header_inherit merge; ändern, sonst wiederholen Sie die Header in jeder Location oder binden sie per include ein.
server {
# ...
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
}
Security-Header prüfen: so messen Sie richtig
Prüfen Sie nur Websites, die Ihnen gehören oder für die Sie eine Erlaubnis haben. Für das Abrufen der eigenen Header genügen Bordmittel.
Schritt 1: Header per GET abrufen, nicht per HEAD
Der naheliegende Befehl curl -I schickt eine HEAD-Anfrage. Laut RFC 9110 soll ein Server darauf dieselben Header senden wie bei GET, er darf aber Header weglassen, deren Wert erst beim Erzeugen des Inhalts feststeht. Genau dort setzen manche Anwendungen ihre Security-Header. Messen Sie deshalb mit einer echten GET-Anfrage und verwerfen Sie nur den Inhalt:
curl -s -D - -o /dev/null https://www.example.com/
Prüfen Sie danach mehrere Seitentypen auf einmal, darunter eine Unterseite, eine Datei und eine Fehlerseite. Ein angehängter Parameter wie ?cb=1 umgeht zwischengespeicherte Antworten. Vergleichen Sie zusätzlich ohne Parameter, denn das ist die Antwort, die Ihre Besucher bekommen:
for p in / /kontakt.html /gibt-es-nicht /favicon.ico; do
echo "== $p"
curl -s -D - -o /dev/null "https://www.example.com$p" \
| grep -i -E '^(content-security-policy|strict-transport-security|x-content-type-options|referrer-policy|permissions-policy)'
done
Schritt 2: Browser-Konsole lesen
Öffnen Sie die Entwicklerwerkzeuge (F12) und laden Sie die Seite neu. Im Reiter „Netzwerk“ sehen Sie bei der ersten Anfrage die tatsächlich angekommenen Antwort-Header. Im Reiter „Konsole“ meldet der Browser jede Ressource, die die CSP blockiert hat, mit der verletzten Direktive. Klicken Sie danach durch die wichtigen Funktionen: Formular absenden, Menü öffnen, Video starten, Cookie-Hinweis bestätigen. Viele Verstöße treten erst bei einer Aktion auf.
Schritt 3: Neue Policy zuerst im Report-Only-Modus
Mit Content-Security-Policy-Report-Only wird die Policy nicht durchgesetzt, der Browser meldet Verstöße nur in der Konsole und an einen Endpunkt, wenn Sie einen angeben. Laut MDN können beide Header gleichzeitig gesetzt sein: Die bestehende Policy wirkt weiter, die neue wird nur getestet. Für Berichte empfiehlt MDN report-to mit dem Header Reporting-Endpoints. Das ältere report-uri gilt laut CSP-Spezifikation als veraltet, MDN rät aber, beide anzugeben, solange report-to nicht in allen Browsern unterstützt wird.
Reporting-Endpoints: csp="https://www.example.com/csp-berichte"
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; report-to csp; report-uri https://www.example.com/csp-berichte
Lassen Sie den Report-Only-Modus laufen, bis keine neuen berechtigten Verstöße mehr auftauchen, und übernehmen Sie die Policy dann in Content-Security-Policy. Für einen schnellen Überblick über die öffentlich sichtbaren Einstellungen gibt es kostenlose Prüfwerkzeuge, die wir im 15-Minuten-Check für Ihre Website einordnen.
Die häufigen Fehler
1. unsafe-inline in script-src
Der häufigste Grund, warum eine vorhandene CSP kaum schützt. Oft wurde 'unsafe-inline' ergänzt, weil nach dem Einschalten etwas nicht mehr funktionierte. Ersetzen Sie es durch Hashes oder Nonces und verlagern Sie Inline-Event-Handler in Skriptdateien. Dasselbe gilt für 'unsafe-eval', das laut MDN anders als 'unsafe-inline' auch neben Hashes und Nonces wirksam bleibt.
2. Zu breite Quellen
Einträge wie https:, * oder ganze Domains großer Anbieter mit vielen Kunden erlauben weit mehr als die eine Datei, die Sie brauchen. Liegt auf einer erlaubten Domain beliebiger fremder Inhalt, kann ein Angreifer sein Skript von dort laden. Nennen Sie so konkrete Quellen wie möglich, und bei script-src lieber Hashes oder Nonces als Domain-Listen.
3. CSP nur als Meta-Tag
Eine CSP lässt sich auch über <meta http-equiv="Content-Security-Policy"> setzen. Laut CSP-Spezifikation wirken dort aber frame-ancestors, report-uri und sandbox nicht, und der Report-Only-Modus wird im Meta-Tag gar nicht unterstützt. Ein Meta-Tag schützt also nicht gegen Klickjacking. Wenn Sie auf den Server oder das Hosting Zugriff haben, setzen Sie die CSP als HTTP-Header.
4. Header nur auf der Startseite
Header, die im Code einer bestimmten Seite oder in einem einzelnen location-Block gesetzt werden, fehlen auf allen anderen Antworten. Typische Lücken: Unterseiten mit eigener Regel, Fehlerseiten ohne always, Dateien aus einem anderen Verzeichnis oder einem CDN, Antworten aus Serverless-Functions bei Netlify. Die Schleife aus Schritt 1 deckt das in einer Minute auf.
5. HSTS zu früh mit preload
Wer includeSubDomains; preload setzt und die Domain einträgt, bevor alle Subdomains HTTPS können, sperrt Besucher von diesen Subdomains aus, und die Austragung dauert Monate. Beginnen Sie ohne preload und erweitern Sie, wenn alles läuft.
6. Veraltete Header als Ersatz
X-XSS-Protection ersetzt keine CSP, und X-Frame-Options: ALLOW-FROM ignorieren aktuelle Browser laut MDN vollständig. Für erlaubte Einbettungen brauchen Sie frame-ancestors mit den konkreten Domains.
Checkliste
| Bereich | Maßnahme |
|---|---|
| CSP | Als HTTP-Header, mit default-src, script-src ohne 'unsafe-inline', object-src 'none', base-uri, form-action, frame-ancestors |
| Inline-Skripte | Per Hash oder Nonce erlaubt, keine Inline-Event-Handler |
| Quellen | So konkret wie möglich, kein * und kein https: in script-src |
| HSTS | max-age mindestens ein Jahr, includeSubDomains erst nach Prüfung aller Subdomains, preload nur bewusst |
| Weitere Header | nosniff, Referrer-Policy ausdrücklich gesetzt, Permissions-Policy für ungenutzte Funktionen |
| Altlasten | X-XSS-Protection entfernt oder 0, kein ALLOW-FROM |
| Abdeckung | Header auf Unterseiten, Dateien und Fehlerseiten per GET gemessen |
| Einführung | Neue CSP zuerst im Report-Only-Modus, Konsole bei allen wichtigen Funktionen sauber |
Was Header nicht leisten
Security-Header sind eine zweite Verteidigungslinie. Eine CSP verhindert, dass eingeschleuste Skripte laufen, sie verhindert nicht, dass jemand über eine Lücke in Ihrem Formular, Ihrer API oder Ihrem Login an Daten kommt. Ob Ihre Anwendung solche Lücken hat, zeigt erst eine Prüfung der Anwendung selbst. Werden dabei personenbezogene Daten tatsächlich abgerufen, kann das eine Meldepflicht nach Art. 33 DSGVO auslösen. Ob das im Einzelfall zutrifft, ist eine Rechtsfrage. Dieser Artikel ist keine Rechtsberatung.
Sind Ihre Header wirklich wirksam?
Wir prüfen Ihre Website im schriftlich vereinbarten Umfang: ausgelieferte Security-Header auf allen Seitentypen, die CSP gegen die tatsächlich geladenen Skripte, Einbettung und Weiterleitungen, dazu Formulare, Anmeldung und Schnittstellen. Jeder Befund kommt mit einem nachvollziehbaren Nachweis und einem konkreten Korrekturvorschlag für Ihr Hosting. Mehr dazu unter Penetrationstest.
Website-Sicherheitscheck anfragenCyberSec42 ist eine unabhängige technische Sicherheitsprüfung, keine akkreditierte Zertifizierungsstelle und keine Rechtsberatung. CyberSec42 steht in keiner Verbindung zu Vercel, Netlify, Apache oder nginx.
Häufige Fragen
Reicht eine Content Security Policy als Meta-Tag?
Für den Schutz vor eingeschleusten Skripten wirkt sie auch als Meta-Tag. frame-ancestors, report-uri, sandbox und der Report-Only-Modus funktionieren dort aber nicht. Gegen Klickjacking brauchen Sie den HTTP-Header.
Brauche ich X-Frame-Options noch?
frame-ancestors in der CSP überstimmt X-Frame-Options laut CSP-Spezifikation und ist flexibler. X-Frame-Options: DENY zusätzlich zu senden schadet nicht und deckt ältere Browser ab.
Soll ich X-XSS-Protection setzen?
Nein. MDN führt den Header als veraltet, und OWASP rät, ihn wegzulassen oder mit 0 abzuschalten. Den Schutz übernimmt eine CSP ohne 'unsafe-inline' in script-src.
Warum zeigt curl -I andere Header als der Browser?
curl -I sendet eine HEAD-Anfrage, bei der ein Server laut RFC 9110 Header weglassen darf, die erst beim Erzeugen der Seite entstehen. Dazu kommen Caches, die ältere Antworten ausliefern. Messen Sie per GET mit curl -s -D - -o /dev/null, mit und ohne Cache-Buster.
Kann eine CSP meine Website kaputt machen?
Ja, wenn sie Skripte, Schriften oder Verbindungen blockiert, die Ihre Seite braucht. Deshalb starten Sie mit Content-Security-Policy-Report-Only, lesen die Konsole und Berichte und schalten erst danach scharf.
Ersetzen gute Security-Header einen Penetrationstest?
Nein. Header mildern bestimmte Angriffe im Browser ab. Lücken in Anmeldung, Rechteprüfung, Formularen oder Schnittstellen finden sie nicht. Dafür braucht es eine Prüfung der Anwendung selbst.
Weiterlesen
- Website-Sicherheit prüfen
- Website-Sicherheit prüfen: der 15-Minuten-Check
- WordPress absichern: Leitfaden mit Checkliste
- Shopify-Shop absichern: Checkliste für Händler
- Website gehackt: was tun? Erste Hilfe für KMU
- Leistung: Penetrationstest
Quellen
- W3C: Content Security Policy Level 3
- MDN: Content Security Policy (CSP)
- MDN: CSP frame-ancestors
- MDN: X-Frame-Options
- MDN: X-XSS-Protection
- MDN: Strict-Transport-Security
- MDN: X-Content-Type-Options
- MDN: Referrer-Policy
- MDN: Permissions-Policy
- W3C: Referrer Policy
- RFC 6797: HTTP Strict Transport Security (HSTS)
- RFC 9110: HTTP Semantics, Abschnitt 9.3.2 HEAD
- HSTS Preload List Submission
- OWASP Secure Headers Project
- OWASP HTTP Headers Cheat Sheet
- Vercel Docs: vercel.json, headers
- Netlify Docs: Custom headers
- Apache HTTP Server: mod_headers
- nginx: ngx_http_headers_module
- EUR-Lex: Datenschutz-Grundverordnung (EU) 2016/679