security: HTTPS-only-Header per HTTPS_ENABLED-Flag steuern

`upgrade-insecure-requests` (CSP) + HSTS sperrten den Browser bei direktem
http://ip:port-Zugriff aus (ERR_SSL_PROTOCOL_ERROR auf den Vite-Assets,
weil Browser sie via https laden wollte).

Beide Header sind jetzt default OFF und werden nur gesetzt, wenn
HTTPS_ENABLED=true – also sobald ein TLS-Reverse-Proxy (Caddy/Traefik/Nginx)
vor OpenCRM steht. Lokale + non-TLS-Deployments laufen damit ohne Stolperfalle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 18:00:01 +02:00
parent 63ebf3e75f
commit 3fb1925a98
3 changed files with 22 additions and 2 deletions
+15 -2
View File
@@ -151,6 +151,13 @@ app.use((_req, res, next) => {
next();
});
// HTTPS-only-Header (HSTS + upgrade-insecure-requests) nur setzen, wenn
// wirklich TLS davor läuft sonst sperrt sich die App auf direkt-via-IP-
// Deployments (Browser versucht /assets/* via https zu laden → SSL-Error).
// Aktivieren mit HTTPS_ENABLED=true in der .env, sobald ein TLS-Proxy
// (Caddy/Traefik/Nginx) vor OpenCRM steht.
const httpsEnabled = process.env.HTTPS_ENABLED === 'true';
app.use(
helmet({
contentSecurityPolicy: {
@@ -166,10 +173,16 @@ app.use(
'object-src': ["'none'"],
'base-uri': ["'self'"],
'form-action': ["'self'"],
'upgrade-insecure-requests': [], // wenn HTTPS verfügbar, dann erzwingen
// useDefaults bringt 'upgrade-insecure-requests' selbst mit explizit
// auf null setzen entfernt es aus dem Header (helmet-API).
'upgrade-insecure-requests': httpsEnabled ? [] : null,
},
},
// Cross-Origin-Resource-Policy: "same-site" für SPA mit gleicher Origin
// HSTS nur wenn echt TLS vorhanden sonst sperrt sich der Browser
// dauerhaft aus, wenn die App direkt via http://ip:port erreichbar ist.
strictTransportSecurity: httpsEnabled
? { maxAge: 31536000, includeSubDomains: true }
: false,
crossOriginResourcePolicy: { policy: 'same-site' },
}),
);