X-Content-Type-Options für Nginx konfigurieren

Schritt-für-Schritt-Anleitung: nosniff-Header setzen, MIME-Types korrekt konfigurieren und Upload-Verzeichnisse gegen MIME-Sniffing absichern.

Nginx · Schritt für Schritt

X-Content-Type-Options auf Nginx

Nginx setzt den Header mit der Direktive add_header X-Content-Type-Options "nosniff" always;. Das Schlüsselwort always ist entscheidend — ohne es fehlt der Header bei Fehlerantworten (4xx, 5xx). Wichtig: Bei mehreren add_header-Direktiven in verschachtelten Blöcken werden Header aus übergeordneten Blöcken nicht vererbt. Den Header in jedem Block explizit setzen, der eigene Header definiert.

Diese Anleitung zeigt die Konfiguration in vier Schritten: Header global setzen, MIME-Types prüfen, Upload-Pfade absichern und verifizieren.

1 Schritt 1 von 4

Header setzen

Fügen Sie add_header X-Content-Type-Options "nosniff" always; in den http-Block Ihrer nginx.conf ein. Das always-Keyword erzwingt den Header auch bei Fehlerantworten — ohne es fehlt er bei 404- und 500-Seiten.

/etc/nginx/nginx.conf add_header
# /etc/nginx/nginx.conf oder /etc/nginx/conf.d/security.conf
http {
    # Globaler Security-Header — gilt für alle Server-Blöcke
    add_header X-Content-Type-Options "nosniff" always;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Weitere empfohlene Security-Header
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
Nginx-Vererbungsfalle: Wenn ein location-Block eigene add_header-Direktiven enthält, werden Header aus übergeordneten Blöcken nicht automatisch vererbt. Den X-Content-Type-Options-Header in jedem solchen Block explizit wiederholen.
Konfiguration prüfen und neu laden:
sudo nginx -t && sudo systemctl reload nginx
2 Schritt 2 von 4

MIME-Types korrekt konfigurieren

nosniff blockiert Ressourcen mit falschem Content-Type. Stellen Sie sicher, dass Nginx die richtigen MIME-Typen deklariert — besonders für JavaScript (text/javascript per RFC 9239) und CSS. Die Datei /etc/nginx/mime.types sollte für moderne Browser aktuell sein.

/etc/nginx/mime.types MIME-Typen
# /etc/nginx/mime.types — Auszug der kritischen Typen
types {
    # JavaScript — RFC 9239 Standard
    text/javascript                    js mjs;

    # Stylesheets
    text/css                           css;

    # JSON
    application/json                   json;

    # Bilder
    image/svg+xml                      svg svgz;
    image/png                          png;
    image/jpeg                         jpg jpeg;

    # Fonts
    font/woff2                         woff2;
    font/woff                          woff;
}
Prüfen Sie mit curl -sI https://ihre-domain.de/app.js | grep content-type, ob JavaScript als text/javascript ausgeliefert wird. Ältere Nginx-Versionen verwenden noch application/javascript — das funktioniert, aber text/javascript ist der aktuelle Standard.
3 Schritt 3 von 4

Upload-Verzeichnisse absichern

Upload-Verzeichnisse sind das primäre Ziel von MIME-Sniffing-Angriffen. Erzwingen Sie für alle Dateien in diesen Pfaden Content-Disposition: attachment (Download statt Browser-Rendering) und deaktivieren Sie PHP-Ausführung im Upload-Verzeichnis.

/etc/nginx/conf.d/uploads.conf Upload-Schutz
# Upload-Verzeichnis absichern — Script-Ausführung verhindern
server {
    listen 443 ssl;
    server_name ihre-domain.de;

    # Globaler Header
    add_header X-Content-Type-Options "nosniff" always;

    location /uploads/ {
        # Header auch hier explizit setzen (Vererbung greift nicht bei eigenem add_header)
        add_header X-Content-Type-Options "nosniff" always;

        # Download erzwingen statt Browser-Rendering
        add_header Content-Disposition 'attachment' always;

        # PHP / CGI-Ausführung in Upload-Pfad verbieten
        location ~ .php$ {
            deny all;
            return 404;
        }
    }
}
Subdomain für User-Uploads

Für maximale Isolation liefern Sie user-generierte Inhalte auf einer separaten Domain (z.B. cdn.ihre-domain.de) aus. Damit ist auch der Same-Origin-Schutz aktiv — Scripts aus der Upload-Domain können nicht auf Cookies der Hauptdomain zugreifen.

4 Schritt 4 von 4

Verifizierung

Nach dem Reload prüfen Sie den Header mit curl. Testen Sie sowohl die Hauptseite als auch statische Assets und das Upload-Verzeichnis — besonders wenn Sie verschachtelte location-Blöcke verwenden.

Terminal Verifizierung
# 1. Nginx-Konfiguration prüfen
sudo nginx -t

# 2. Nginx neu laden (ohne Downtime)
sudo systemctl reload nginx

# 3. Header verifizieren
curl -sI https://ihre-domain.de | grep -i x-content-type

# Erwartete Ausgabe:
# x-content-type-options: nosniff

# 4. Upload-Verzeichnis prüfen
curl -sI https://ihre-domain.de/uploads/test.jpg | grep -i content-disposition
# Erwartete Ausgabe: content-disposition: attachment
Wolf-Agents Web Security Check

Der Wolf-Agents Scanner prüft automatisch, ob X-Content-Type-Options: nosniff auf Ihrer Domain gesetzt ist — inklusive Punktabzug bei fehlenden oder falschen Werten.

Wie steht Ihre Domain bei X-Content-Type-Options?

Prüfen Sie es jetzt — kostenlos, ohne Registrierung, mit 166 Prüfpunkte.

Häufig gestellte Fragen

Wo soll ich add_header X-Content-Type-Options in Nginx platzieren?

Am besten im http-Block der nginx.conf, damit der Header für alle Server gilt. Alternativ in jedem server-Block. Wichtig: Das Schlüsselwort always sorgt dafür, dass der Header auch bei Fehlerantworten (4xx, 5xx) gesendet wird — ohne always fehlt er bei Fehlerseiten.

Muss ich die MIME-Types in Nginx manuell konfigurieren?

Nginx lädt standardmäßig mime.types aus /etc/nginx/mime.types. Diese Datei enthält für .js bereits text/javascript und für .css text/css. Sie müssen nur prüfen, ob Ihre nginx.conf include /etc/nginx/mime.types; enthält und ob die Datei aktuell ist.

Wie verhindere ich Script-Ausführung in Upload-Verzeichnissen?

Erstellen Sie einen location-Block für Ihr Upload-Verzeichnis mit: location /uploads/ { add_header Content-Disposition "attachment"; add_header X-Content-Type-Options "nosniff" always; } — das erzwingt Download statt Browser-Rendering für alle Dateien in diesem Pfad.

Überschreibt ein innerer location-Block den äußeren add_header?

Ja — das ist ein häufiger Nginx-Fallstrick. add_header-Direktiven werden NICHT vererbt, wenn ein location-Block eigene add_header-Direktiven enthält. Setzen Sie X-Content-Type-Options daher in JEDEM location-Block, der eigene Header definiert, oder nutzen Sie map-Direktiven.

Wie teste ich, ob nosniff korrekt gesetzt ist?

Mit curl -sI https://ihre-domain.de | grep -i x-content-type. Sie sollten X-Content-Type-Options: nosniff in der Ausgabe sehen. Alternativ: Browser DevTools → Network → Response Headers für eine beliebige Ressource.