fix(nginx): Security-Header in überschreibenden location-Blöcken wiederholen

nginx vererbt add_header nicht in Blöcke, die eigene add_header setzen.
Dadurch gingen X-Frame-Options, X-Content-Type-Options und
X-XSS-Protection ausgerechnet bei den HTML-Antworten verloren – jeder
location-Block mit Cache-Control hat sie stillschweigend abgeschaltet.

Verifiziert: nginx -t ist für alle drei Konfigurationen erfolgreich.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
thomas 2026-08-25 08:12:15 +02:00
parent 81b21da499
commit 474383d17b
3 changed files with 84 additions and 3 deletions

View File

@ -27,19 +27,28 @@ server {
gzip_types text/plain text/xml application/xml+rss application/json;
gzip_disable "msie6";
# Security headers
# Security headers.
# ACHTUNG: nginx vererbt add_header nicht in Bloecke, die eigene add_header
# setzen - deshalb sind diese drei Zeilen in jedem solchen location-Block
# wiederholt. Beim Anlegen neuer Bloecke mit add_header daran denken.
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Cache static assets (images, fonts)
location ~* \.(jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
expires 1y;
add_header Cache-Control "public, immutable";
}
# JS and CSS - no compression, short cache
location ~* \.(js|css)$ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
expires 1h;
add_header Cache-Control "public, no-transform";
gzip off;
@ -47,6 +56,9 @@ server {
# Service Worker - never cache
location = /sw.js {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires 0;
}
@ -79,6 +91,9 @@ server {
# Service Worker for subpath deployment
location = /drohnenfuehrer/sw.js {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires 0;
alias /usr/share/nginx/html/sw.js;
@ -86,6 +101,9 @@ server {
# index.html - never cache so new builds are picked up immediately
location = /index.html {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
@ -93,6 +111,9 @@ server {
# SPA fallback for subpath deployment (/drohnenfuehrer)
location ^~ /drohnenfuehrer/ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
rewrite ^/drohnenfuehrer(/.*)$ $1 break;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache, no-store, must-revalidate";
@ -102,6 +123,9 @@ server {
# SPA fallback - serve index.html for all routes
location / {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
@ -110,6 +134,9 @@ server {
# Health check endpoint
location /health {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;

View File

@ -27,19 +27,28 @@ server {
gzip_types text/plain text/xml application/xml+rss application/json;
gzip_disable "msie6";
# Security headers
# Security headers.
# ACHTUNG: nginx vererbt add_header nicht in Bloecke, die eigene add_header
# setzen - deshalb sind diese drei Zeilen in jedem solchen location-Block
# wiederholt. Beim Anlegen neuer Bloecke mit add_header daran denken.
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Cache static assets (images, fonts)
location ~* \.(jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
expires 1y;
add_header Cache-Control "public, immutable";
}
# JS and CSS - no compression, short cache
location ~* \.(js|css)$ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
expires 1h;
add_header Cache-Control "public, no-transform";
gzip off;
@ -47,6 +56,9 @@ server {
# Service Worker - never cache
location = /sw.js {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires 0;
}
@ -79,6 +91,9 @@ server {
# Service Worker for subpath deployment
location = /nachsuche/sw.js {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires 0;
alias /usr/share/nginx/html/sw.js;
@ -86,6 +101,9 @@ server {
# index.html - never cache so new builds are picked up immediately
location = /index.html {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
@ -93,6 +111,9 @@ server {
# SPA fallback for subpath deployment (/nachsuche)
location ^~ /nachsuche/ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
rewrite ^/nachsuche(/.*)$ $1 break;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache, no-store, must-revalidate";
@ -102,6 +123,9 @@ server {
# SPA fallback - serve index.html for all routes
location / {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
@ -110,6 +134,9 @@ server {
# Health check endpoint
location /health {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;

View File

@ -27,19 +27,28 @@ server {
gzip_types text/plain text/xml application/xml+rss application/json;
gzip_disable "msie6";
# Security headers
# Security headers.
# ACHTUNG: nginx vererbt add_header nicht in Bloecke, die eigene add_header
# setzen - deshalb sind diese drei Zeilen in jedem solchen location-Block
# wiederholt. Beim Anlegen neuer Bloecke mit add_header daran denken.
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Cache static assets (images, fonts)
location ~* \.(jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
expires 1y;
add_header Cache-Control "public, immutable";
}
# JS and CSS - no compression, short cache
location ~* \.(js|css)$ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
expires 1h;
add_header Cache-Control "public, no-transform";
gzip off;
@ -47,6 +56,9 @@ server {
# Service Worker - never cache
location = /sw.js {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires 0;
}
@ -79,6 +91,9 @@ server {
# Service Worker for subpath deployment
location = /stoeberhunde/sw.js {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires 0;
alias /usr/share/nginx/html/sw.js;
@ -86,6 +101,9 @@ server {
# index.html - never cache so new builds are picked up immediately
location = /index.html {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
@ -93,6 +111,9 @@ server {
# SPA fallback for subpath deployment (/stoeberhunde)
location ^~ /stoeberhunde/ {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
rewrite ^/stoeberhunde(/.*)$ $1 break;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache, no-store, must-revalidate";
@ -102,6 +123,9 @@ server {
# SPA fallback - serve index.html for all routes
location / {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
@ -110,6 +134,9 @@ server {
# Health check endpoint
location /health {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;