HTTP-Sicherheits-Header sind die einfachste, billigste und wirkungsvollste Härtungs-Schicht für eine Web-App — ein paar Zeilen in der Server-Konfig, und mehrere Klassen Angriffe sind blockiert oder massiv erschwert. Dieser Artikel gibt eine Übersicht über die wichtigen Header, was sie tun, was sie nicht tun, welche modern sind und welche als veraltet gelten — plus konkrete Beispiel-Konfigurationen für nginx, Caddy und Express.

Der moderne Header-Stack

Eine voll-gehärtete Response-Header-Konfig sieht in etwa so aus:

HTTP secure-headers-modern.txt
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123' 'strict-dynamic'; object-src 'none'; base-uri 'self'
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin

Dieser Stack adressiert die Hauptklassen: Protocol-Downgrade (HSTS), XSS und Code-Injection (CSP), MIME-Confusion (nosniff), Information-Leakage (Referrer-Policy), Hardware-Permission-Missbrauch (Permissions-Policy), Spectre-Side-Channels (COOP/COEP/CORP).

Header-für-Header

HeaderZweckVertieft in
Strict-Transport-SecurityHTTPS erzwingen, Downgrade verhindernhsts-und-https-only
Content-Security-PolicySkript-/Ressource-Quellen einschränken (XSS-Schutz)csp-deployment, Kap 11
X-Content-Type-OptionsMIME-Sniffing deaktivierenunten
Referrer-PolicyReferer-Header bei Navigation steuernunten
Permissions-PolicyBrowser-APIs einschränken (Kamera, Mic, etc.)permissions-policy
Cross-Origin-Opener-PolicyCross-Origin-Window-Isolationcoop-coep-corp
Cross-Origin-Embedder-PolicyEmbed-Ressourcen-Anforderungencoop-coep-corp
Cross-Origin-Resource-PolicyWer darf diese Ressource ladencoop-coep-corp
Access-Control-Allow-OriginCORS — Cross-Origin-Requests erlaubencors
Set-Cookie (mit Flags)Cookie-Eigenschaftencookie-flags-und-attribute

X-Content-Type-Options — der schnelle Win

X-Content-Type-Options: nosniff deaktiviert das MIME-Sniffing im Browser. Ohne diesen Header rät der Browser den Content-Type anhand des Datei-Inhalts — und kann ein als text/plain ausgeliefertes File als HTML/JavaScript interpretieren, wenn der Anfang verdächtig aussieht.

Wirkung: Stored-XSS via User-Upload mit verfälschter Extension funktioniert nicht mehr, wenn der Server den korrekten Content-Type setzt und nosniff aktiv ist.

Konfiguration: ein einziger Header, immer setzen. Keine Trade-offs.

HTTP nosniff-header.txt
X-Content-Type-Options: nosniff

Referrer-Policy — Privacy + Sicherheit

Der Referer-Header (historisch falsch geschrieben) wird vom Browser bei Navigation mitgeschickt — die URL der vorigen Seite. Ohne Steuerung leakt das:

  • Session-Tokens in URLs (Anti-Pattern, aber existiert).
  • Interne URLs in externe Klicks.
  • Such-Queries der vorigen Seite.

Empfohlene Policy:

HTTP referrer-policy-recommended.txt
Referrer-Policy: strict-origin-when-cross-origin

Was das macht:

  • Same-Origin-Requests: voller Referer (https://app.example.com/private-page).
  • Cross-Origin auf HTTPS-Ziel: nur Origin (https://app.example.com).
  • Cross-Origin auf HTTP-Ziel: gar nichts.

Default in modernen Browsern seit 2020 — explizit setzen schadet trotzdem nicht (Klarheit für Audit).

Alternativen:

  • no-referrer — niemals senden. Hart, kann Analytics brechen.
  • origin — immer nur Origin (auch Same-Origin).
  • same-origin — bei Cross-Origin gar nichts.

Deprecated und veraltete Header

Manche Header tauchen noch in alten Empfehlungs-Artikeln auf, sind aber nicht mehr nötig oder sogar kontraproduktiv:

HeaderStatusWas stattdessen
X-XSS-ProtectionDeprecated — alle modernen Browser ignorieren oder haben es entferntCSP
X-Frame-OptionsFunktioniert, aber CSP frame-ancestors ist modernerCSP frame-ancestors
Public-Key-Pins (HPKP)Komplett deprecated, kein Browser unterstütztCertificate Transparency Log (passiv)
Expect-CTDeprecated mit CT-Pflicht 2024Nichts (CT ist Default)
Feature-PolicyUmbenannt zu Permissions-PolicyPermissions-Policy

Hinweis zu X-Frame-Options: wenn die App noch alte Browser unterstützen muss (Stand 2026 selten), kann es als Fallback parallel zu frame-ancestors gesetzt werden. Moderne Apps brauchen nur frame-ancestors.

X-XSS-Protection bewusst weglassen: der Header hatte in alten IE/Edge-Versionen sogar gefährliche Bugs (selbst-erzeugte XSS-Lücken durch fehlerhafte Auto-Sanitization). Heute irrelevant.

Konfiguration in den wichtigsten Servern

nginx:

Nginx nginx-security-headers.conf
server {
    # ... TLS-Config ...

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    add_header Cross-Origin-Opener-Policy "same-origin" always;
    add_header Cross-Origin-Resource-Policy "same-origin" always;

    # CSP wird oft pro Location gesetzt, weil sie pro App unterschiedlich ist
    add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'" always;

    # ...
}

Wichtig: always lässt nginx den Header auch bei Error-Responses (4xx/5xx) setzen. Ohne always werden Header bei Error-Pages weggelassen — schlechte Default-Wahl.

Caddy:

Caddy caddyfile-security-headers
app.example.com {
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        Referrer-Policy "strict-origin-when-cross-origin"
        Permissions-Policy "camera=(), microphone=(), geolocation=()"
        Cross-Origin-Opener-Policy "same-origin"
        Cross-Origin-Resource-Policy "same-origin"
        Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'"
    }
    reverse_proxy localhost:3000
}

Express (Helmet):

JavaScript express-helmet.js
import helmet from 'helmet';

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'strict-dynamic'"],
      objectSrc: ["'none'"],
      baseUri: ["'self'"],
    },
  },
  strictTransportSecurity: { maxAge: 31536000, includeSubDomains: true, preload: true },
  referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
  crossOriginOpenerPolicy: { policy: 'same-origin' },
  crossOriginResourcePolicy: { policy: 'same-origin' },
}));

Helmet setzt die meisten Security-Header mit sicheren Defaults. Ergänzungen (CSP-Details, Permissions-Policy) gehören explizit konfiguriert.

Selbst-Test

Online-Scanner:

CLI:

Bash curl-header-check.sh
# Headers ausgeben
curl -sI https://app.example.com | grep -iE 'strict-transport|content-security|x-content-type|referrer|permissions|cross-origin'

# nikto / nuclei für vollständige Scans
nuclei -t http/misconfiguration/http-missing-security-headers.yaml -u https://app.example.com

In CI:

Tools wie Nuclei oder eigene Scripts können als CI-Step laufen — Build failed wenn ein Header fehlt. Verhindert Regression bei Config-Änderungen.

Header-Konflikte und Edge-Cases

Multiple Headers: wenn sowohl Reverse-Proxy als auch App-Server denselben Header setzen, kann es zu Duplikaten kommen — abhängig vom Verhalten des Proxies entweder beide gesetzt (Browser nimmt unterschiedlich), oder einer überschrieben.

Pattern: entscheiden, wo Header gesetzt werden — entweder Reverse-Proxy (alle in nginx/Caddy) oder App-Server (Helmet), nicht beides. Bei vorhandenem CDN/Reverse-Proxy in der Chain ist es oft praktischer, Header dort zu setzen.

Conditional Headers: manche Header sollen pro Pfad anders sein (z. B. CSP für Admin-Panel strikter als für Public-Page). Pro-Location-Config in nginx oder Per-Route-Middleware in Express.

Header-Größe: Cookies plus Header haben in HTTP/1.1 ein Soft-Limit von ~8 KB. Zu viele/zu lange Header (CSP mit vielen Quellen) können Probleme machen. In HTTP/2 weniger relevant, aber gut, schlank zu bleiben.

Interessantes

Reporting-Endpoints für CSP, COEP, Permissions-Policy

Moderne Header unterstützen Report-Only-Modi und Reporting-Endpoints (report-to, report-uri). Damit kann man eine neue Policy ausrollen und beobachten, was Violations triggert, bevor man enforcement aktiviert. Vertieft in csp-deployment.

securityheaders.com gibt Grades aus, nicht Wahrheit

Ein A+ bei securityheaders.com bedeutet: alle empfohlenen Header sind gesetzt. Bedeutet NICHT: deine App ist sicher. Eine App mit perfektem Header-Score kann trotzdem SQL-Injection, IDOR, Logik-Bugs haben. Header sind eine Schicht, nicht die Sicherheit.

HTTP-Headers im Single-Page-App-Setup

Bei SPAs mit eigenem API-Backend müssen die Header auf der Backend-API (für API-Responses) plus auf dem CDN (für SPA-Hosting) gesetzt werden. Beide Stacks bedacht — sonst leakt entweder die API oder das HTML.

Server-Header verraten Tech-Stack

Server: nginx/1.24.0 oder X-Powered-By: Express sind Info für Angreifer — exakte Version macht CVE-Suche trivial. Patterns: Server-Header entfernen oder generisch (server_tokens off; in nginx, app.disable('x-powered-by') in Express). Defense-in-Depth, keine Hauptschutz-Schicht, aber kostenlos.

HTTP/3 ändert Header nicht — aber Setup-Stack

Moderne TLS-Stacks (Quiche, nginx 1.25+, Caddy) sprechen HTTP/3 (QUIC). Header bleiben gleich; nur Transport-Layer ändert sich. Wenn der Stack HTTP/3 spricht, automatisch über Alt-Svc-Header advertised. Browser fallbacks auf HTTP/2 wenn QUIC blockiert ist.

CDN-Cache und Vary-Header

Header, die pro User unterschiedlich sind (z. B. CSP mit nonce), brauchen einen Cache-Control: private. Sonst cached der CDN den Response mit der Nonce für andere User — XSS-Schutz bricht. Pattern: nonce-haltige Responses immer als private markieren, nicht CDN-cachebar.

Header-Stack-Diff zwischen Production und Staging

Production-Stack hat hardened Header, Staging meist nicht (für Debug-Zwecke). Risiko: Bugs zeigen sich erst in Prod. Pattern: Staging-Stack mit production-identischen Headers, plus separate Dev-Bypass via Header (X-Dev-Disable-CSP: true) oder Debug-Tool — strikt nur in Dev-Umgebung.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Secure Headers & Cookies

Zur Übersicht