fix: move security headers to middleware composition (qa-requested)
- Move CSP, HSTS, Referrer-Policy, and Permissions-Policy from next.config.ts to middleware - Compose headers with next-intl middleware to ensure they propagate through rewrites - Security headers now set via response.headers.set() in middleware after i18n routing - All security headers should now appear in HTTP responses Fixes QA issue: headers from next.config.ts not appearing due to middleware rewrites Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
+1
-16
@@ -42,22 +42,7 @@ const nextConfig: NextConfig = {
|
|||||||
key: 'X-Content-Type-Options',
|
key: 'X-Content-Type-Options',
|
||||||
value: 'nosniff',
|
value: 'nosniff',
|
||||||
},
|
},
|
||||||
{
|
// Security headers moved to middleware (CSP, HSTS, Referrer-Policy, Permissions-Policy)
|
||||||
key: 'Content-Security-Policy',
|
|
||||||
value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data: blob: https://mxadgucxhmstlzsbgmoz.supabase.co; connect-src 'self' https://mxadgucxhmstlzsbgmoz.supabase.co; frame-ancestors 'self'; base-uri 'self'; form-action 'self'",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Strict-Transport-Security',
|
|
||||||
value: 'max-age=31536000; includeSubDomains; preload',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Referrer-Policy',
|
|
||||||
value: 'strict-origin-when-cross-origin',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Permissions-Policy',
|
|
||||||
value: 'geolocation=(), microphone=(), camera=(), payment=(), usb=()',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+30
-1
@@ -1,12 +1,41 @@
|
|||||||
import createMiddleware from 'next-intl/middleware';
|
import createMiddleware from 'next-intl/middleware';
|
||||||
import { locales, defaultLocale } from './i18n/config';
|
import { locales, defaultLocale } from './i18n/config';
|
||||||
|
import { NextRequest } from 'next/server';
|
||||||
|
|
||||||
export default createMiddleware({
|
const handleI18nRouting = createMiddleware({
|
||||||
locales,
|
locales,
|
||||||
defaultLocale,
|
defaultLocale,
|
||||||
localePrefix: 'always',
|
localePrefix: 'always',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default function middleware(request: NextRequest) {
|
||||||
|
// Handle i18n routing first
|
||||||
|
const response = handleI18nRouting(request);
|
||||||
|
|
||||||
|
// Add security headers to the response
|
||||||
|
response.headers.set(
|
||||||
|
'Content-Security-Policy',
|
||||||
|
"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data: blob: https://mxadgucxhmstlzsbgmoz.supabase.co; connect-src 'self' https://mxadgucxhmstlzsbgmoz.supabase.co; frame-ancestors 'self'; base-uri 'self'; form-action 'self'"
|
||||||
|
);
|
||||||
|
|
||||||
|
response.headers.set(
|
||||||
|
'Strict-Transport-Security',
|
||||||
|
'max-age=31536000; includeSubDomains; preload'
|
||||||
|
);
|
||||||
|
|
||||||
|
response.headers.set(
|
||||||
|
'Referrer-Policy',
|
||||||
|
'strict-origin-when-cross-origin'
|
||||||
|
);
|
||||||
|
|
||||||
|
response.headers.set(
|
||||||
|
'Permissions-Policy',
|
||||||
|
'geolocation=(), microphone=(), camera=(), payment=(), usb=()'
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: [
|
matcher: [
|
||||||
'/',
|
'/',
|
||||||
|
|||||||
Reference in New Issue
Block a user