Senior #security#csp#middleware
Security headers và CSP với nonce trong Next.js được triển khai thế nào?
⚡ Trả lời nhanh
Header tĩnh (HSTS, X-Content-Type-Options, frame-ancestors...) đặt trong `headers()` của next.config. CSP chặt chẽ dùng nonce cho mỗi request: sinh trong Middleware, gắn vào header `Content-Security-Policy` và `x-nonce`; Next tự áp nonce cho script của nó. Đổi lại trang phải render dynamic.
// middleware.ts
export function middleware(req: NextRequest) {
const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
const csp = `default-src 'self'; script-src 'self' 'nonce-${nonce}' 'strict-dynamic'; ` +
`style-src 'self' 'nonce-${nonce}'; object-src 'none'; frame-ancestors 'none'`;
const headers = new Headers(req.headers);
headers.set("x-nonce", nonce);
headers.set("Content-Security-Policy", csp);
const res = NextResponse.next({ request: { headers } });
res.headers.set("Content-Security-Policy", csp);
return res;
}
// Script tự thêm: const nonce = (await headers()).get("x-nonce")
- Nonce phải khác nhau mỗi request, nên không thể cache tĩnh toàn trang (static/ISR sẽ không dùng được nonce). Cần cân nhắc
'unsafe-inline', hash, hoặc chấp nhận dynamic rendering. - Dev mode cần thêm
'unsafe-eval'cho React; đừng để lọt vào production. - Header nên có:
Strict-Transport-Security,X-Content-Type-Options: nosniff,Referrer-Policy,Permissions-Policy. - Server Actions đã kiểm tra
Originso vớiHost(chống CSRF cơ bản), nhưng vẫn phải xác thực/ủy quyền trong từng action.