Capítulo 34 de 456
Proteja a app contra XSS, clickjacking e code injection com CSP; use nonce dinâmico via Proxy quando precisa permitir scripts inline específicos, ou SRI (experimental) quando quer manter geração estática com CSP estrita.
proxy.ts): gera o nonce por request, seta o header Content-Security-Policy e um header customizado x-nonce antes do render.await connection() pra forçar dynamic rendering.Content-Security-Policy, extrai via padrão 'nonce-{value}' e aplica automaticamente a scripts do framework, bundles JS da página, estilos/scripts inline gerados pelo Next.js e <Script nonce={nonce}>.'unsafe-eval' em dev: React usa eval em desenvolvimento para reconstruir stack traces do servidor no browser; não necessário em produção.experimental.sri.algorithm); permite manter static generation e cache em CDN, mas app-router only e não cobre scripts gerados dinamicamente.import { NextRequest, NextResponse } from 'next/server'
export function proxy(request: NextRequest) {
const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
const isDev = process.env.NODE_ENV === 'development'
const cspHeader = `
default-src 'self';
script-src 'self' 'nonce-${nonce}' 'strict-dynamic'${isDev ? " 'unsafe-eval'" : ''};
style-src 'self' 'nonce-${nonce}';
img-src 'self' blob: data:;
object-src 'none';
base-uri 'self';
frame-ancestors 'none';
upgrade-insecure-requests;
`
const contentSecurityPolicyHeaderValue = cspHeader.replace(/\s{2,}/g, ' ').trim()
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-nonce', nonce)
requestHeaders.set('Content-Security-Policy', contentSecurityPolicyHeaderValue)
const response = NextResponse.next({ request: { headers: requestHeaders } })
response.headers.set('Content-Security-Policy', contentSecurityPolicyHeaderValue)
return response
}
import { headers } from 'next/headers'
import Script from 'next/script'
export default async function Page() {
const nonce = (await headers()).get('x-nonce')
return <Script src="https://www.googletagmanager.com/gtag/js" strategy="afterInteractive" nonce={nonce} />
}
module.exports = {
experimental: { sri: { algorithm: 'sha256' } },
async headers() {
return [{ source: '/(.*)', headers: [{ key: 'Content-Security-Policy', value: cspHeader.replace(/\n/g, '') }] }]
},
}
| Abordagem | Static generation | CDN cache | Custo |
|---|---|---|---|
| Nonce (Proxy) | Não (dynamic obrigatório) | Não por padrão | Maior carga de servidor, sem PPR |
| SRI (experimental) | Sim | Sim | Só cobre scripts conhecidos em build time |
| Versão | Mudança |
|---|---|
| v14.0.0 | Suporte experimental a SRI (hash-based CSP) |
| v13.4.20 | Recomendada para handling correto de nonce e parsing do header CSP |
script-src e connect-src explícitos).matcher no Proxy ignorando prefetches (next-router-prefetch) e assets estáticos pra não gerar overhead desnecessário.script-src/connect-src/img-src, além do nonce.nonce para scripts de terceiro sob CSP.