51 lines
1.8 KiB
JavaScript
51 lines
1.8 KiB
JavaScript
/**
|
||
* Globale Security-Header für Nitro (Nuxt 3).
|
||
*
|
||
* Apache setzt ggf. bereits Header – diese Middleware dient als "Default",
|
||
* damit die App auch ohne Reverse-Proxy sauber gehärtet ist.
|
||
*
|
||
* CSP ist optional und sollte zuerst im Report-Only Modus getestet werden.
|
||
* Siehe ENV:
|
||
* - CSP_ENABLED=true|false
|
||
* - CSP_REPORT_ONLY=true|false
|
||
* - CSP_VALUE="..."
|
||
*/
|
||
|
||
export default defineEventHandler((event) => {
|
||
// Grundsätzlich sinnvolle Header
|
||
setHeader(event, 'X-Content-Type-Options', 'nosniff')
|
||
setHeader(event, 'Referrer-Policy', 'strict-origin-when-cross-origin')
|
||
setHeader(event, 'Permissions-Policy', 'geolocation=(), microphone=(), camera=()')
|
||
|
||
// X-Frame-Options: SAMEORIGIN (DENY wäre strenger, verhindert aber iFrames komplett)
|
||
setHeader(event, 'X-Frame-Options', 'SAMEORIGIN')
|
||
|
||
// Legacy-Header (optional; moderne Browser verlassen sich primär auf CSP)
|
||
setHeader(event, 'X-XSS-Protection', '0')
|
||
|
||
// Optional: CSP
|
||
const cspEnabled = (process.env.CSP_ENABLED || '').toLowerCase() === 'true'
|
||
if (cspEnabled) {
|
||
const reportOnly = (process.env.CSP_REPORT_ONLY || 'true').toLowerCase() !== 'false'
|
||
const cspValue =
|
||
process.env.CSP_VALUE ||
|
||
[
|
||
"default-src 'self'",
|
||
"base-uri 'self'",
|
||
"object-src 'none'",
|
||
"frame-ancestors 'self'",
|
||
// Nuxt lädt Fonts ggf. von Google (siehe nuxt.config.js)
|
||
"font-src 'self' https://fonts.gstatic.com data:",
|
||
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
|
||
// Script: Nuxt kann in Dev eval nutzen; diese CSP ist primär für Produktion gedacht.
|
||
"script-src 'self'",
|
||
"img-src 'self' data: blob:",
|
||
"connect-src 'self'"
|
||
].join('; ')
|
||
|
||
setHeader(event, reportOnly ? 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy', cspValue)
|
||
}
|
||
})
|
||
|
||
|