import { NextResponse, type NextRequest } from 'next/server' /** * Strikte CSP mit Nonce. Kein 'unsafe-inline' fuer Skripte, siehe * docs/07-dateien-und-sicherheit.md. Next.js liest die CSP aus dem Request und * haengt den Nonce an seine eigenen Skript-Tags. * * Im Dev-Server braucht der React Refresh Runtime 'unsafe-eval'. */ export function middleware(request: NextRequest): NextResponse { const nonce = btoa(crypto.randomUUID()) const isDev = process.env.NODE_ENV === 'development' const csp = [ `default-src 'self'`, `script-src 'self' 'nonce-${nonce}' 'strict-dynamic'${isDev ? " 'unsafe-eval'" : ''}`, // Tailwind erzeugt zur Laufzeit keine Styles, aber Next setzt inline-Styles // fuer den Bildplatzhalter. Style-Nonces unterstuetzt Next nicht. `style-src 'self' 'unsafe-inline'`, `img-src 'self' blob: data:`, `font-src 'self'`, // Der SSE-Endpunkt laeuft ueber dieselbe Herkunft. `connect-src 'self'`, `object-src 'none'`, `base-uri 'none'`, `form-action 'self'`, `frame-ancestors 'none'`, `upgrade-insecure-requests`, ].join('; ') const headers = new Headers(request.headers) headers.set('x-nonce', nonce) headers.set('content-security-policy', csp) const response = NextResponse.next({ request: { headers } }) response.headers.set('content-security-policy', csp) return response } export const config = { matcher: [ // Statische Assets und Bild-Optimierung brauchen keine CSP-Berechnung. { source: '/((?!_next/static|_next/image|fonts|favicon.ico).*)', missing: [ { type: 'header', key: 'next-router-prefetch' }, { type: 'header', key: 'purpose', value: 'prefetch' }, ], }, ], }