</>
⌕
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 Origin so với Host (chống CSRF cơ bản), nhưng vẫn phải xác thực/ủy quyền trong từng action.
🃏 Ôn bằng flashcard