Use Cases (Atualizado: 02/06/2026)

Security headers web com Claude Code: CSP, nonce, HSTS e deploy sem quebrar anúncios

Configure CSP, nonce, HSTS, frame-ancestors e security headers com Claude Code em Next.js, Astro, Express e Cloudflare.

Security headers web com Claude Code: CSP, nonce, HSTS e deploy sem quebrar anúncios

Security headers parecem apenas detalhes de resposta HTTP, mas definem regras importantes para o navegador. Eles controlam quais scripts podem executar, se uma área administrativa pode ser carregada dentro de um iframe, quanta informação de referrer vai para sites externos e se recursos como câmera, microfone, localização e pagamento ficam disponíveis.

Claude Code acelera esse trabalho porque consegue ler o repositório, identificar scripts de terceiros, ajustar configurações de framework e sugerir comandos de verificação. O problema é que um pedido vago pode gerar uma política perigosa. Se você pedir apenas “corrija os erros de CSP”, a resposta pode ser algo como script-src * 'unsafe-inline' 'unsafe-eval'. Os erros somem, mas a proteção também.

A abordagem correta é inventariar recursos, publicar Content-Security-Policy-Report-Only, analisar relatórios, ajustar por rota e só então aplicar a CSP em modo enforcement. Este guia cobre CSP, nonce, HSTS, X-Frame-Options, frame-ancestors, Referrer-Policy e Permissions-Policy, com exemplos para Next.js, Astro, Express e Cloudflare Pages. Também inclui CSP report, Security Headers, CSP Evaluator e conflitos comuns com Google Tag Manager, Google Analytics, AdSense, imagens e CDNs. Para a segurança do próprio fluxo com Claude Code, veja também boas práticas de segurança e auditoria de segurança com Claude Code.

Use a documentação oficial como referência: MDN Content-Security-Policy, Next.js CSP guide, MDN Strict-Transport-Security, hstspreload.org, Cloudflare Pages Headers, Helmet, Google Tag Manager CSP e AdSense com CSP.

Comece pelo inventário de recursos

Não copie uma política pronta antes de entender o que o site realmente carrega. Peça ao Claude Code um levantamento explícito.

Projete security headers para este repositório.
Regras:
- Primeiro liste origens externas de script, style, image, font, frame e connect.
- Comece CSP com Report-Only.
- Evite * e unsafe-inline permanente.
- Se Next.js precisar de nonce, explique impacto em renderização dinâmica e cache.
- Verifique Google Analytics, GTM, AdSense, CDN de imagens e YouTube iframe.
- Entregue passos de teste com curl, Security Headers e CSP Evaluator.

Essa etapa evita confusões comuns. frame-src controla quais iframes sua página pode carregar. frame-ancestors controla quem pode colocar sua página dentro de um iframe. Problemas de GA4 geralmente aparecem em connect-src; imagens de CDN em img-src; clickjacking em frame-ancestors.

HeaderPonto de partidaCuidado
Content-Security-PolicyPrimeiro Content-Security-Policy-Report-OnlyNão esconda problemas com *
Strict-Transport-SecurityComece com max-age=300; includeSubDomainspreload só após todos os subdomínios estarem em HTTPS
X-Frame-OptionsDENY ou SAMEORIGINframe-ancestors é mais moderno e granular
Referrer-Policystrict-origin-when-cross-originNão coloque dados sensíveis em URLs
Permissions-PolicyDesative recursos não usadosLibere apenas o que o produto usa
X-Content-Type-OptionsnosniffNormalmente vale para o site inteiro

HSTS preload não deve ser ativado no primeiro dia. O site oficial recomenda aumentar max-age em etapas e alerta que desfazer preload pode demorar. Um subdomínio antigo sem HTTPS ou um domínio de testes esquecido pode virar uma interrupção real.

CSP como rollout controlado

O fluxo mais seguro é observar, classificar e depois aplicar.

flowchart LR
  A["Inventariar recursos"] --> B["Enviar CSP Report-Only"]
  B --> C["Coletar console e reports"]
  C --> D["Separar anúncios, analytics, CDN, iframes e ruído"]
  D --> E["Ativar CSP com nonce ou hash"]
  E --> F["Validar com Security Headers e CSP Evaluator"]

Não adicione todos os domínios relatados. Extensões de navegador, proxies corporativos, tags antigas e tentativas de ataque podem gerar reports. Claude Code ajuda a agrupar, mas a decisão final deve ser baseada no que o produto realmente precisa.

Next.js com nonce

Na documentação atual do App Router, Next.js usa proxy.ts para gerar um nonce por requisição. Projetos antigos podem usar middleware.ts, mas a lógica é a mesma: gerar um valor imprevisível, colocá-lo no request header e usar o mesmo valor em script-src.

Nonce por requisição tem impacto em renderização. Uma página que precisa de nonce novo não combina bem com HTML totalmente estático. Para blogs e landing pages públicas, hashes CSP ou scripts externos podem ser melhores. Para checkout, painel, conta e administração, nonce costuma compensar.

// proxy.ts
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 !== "production";

  const csp = [
    "default-src 'self'",
    `script-src 'self' 'nonce-${nonce}' 'strict-dynamic' ${isDev ? "'unsafe-eval'" : ""} https: http:`,
    `style-src 'self' ${isDev ? "'unsafe-inline'" : `'nonce-${nonce}'`} https://fonts.googleapis.com`,
    "font-src 'self' https://fonts.gstatic.com",
    "img-src 'self' data: blob: https:",
    "connect-src 'self' https://www.google-analytics.com https://analytics.google.com",
    "frame-src 'self' https://www.youtube-nocookie.com",
    "object-src 'none'",
    "base-uri 'self'",
    "form-action 'self'",
    "frame-ancestors 'none'",
    "upgrade-insecure-requests",
    "report-uri /api/csp-report",
  ].join("; ").replace(/\s{2,}/g, " ").trim();

  const requestHeaders = new Headers(request.headers);
  requestHeaders.set("x-nonce", nonce);

  const response = NextResponse.next({ request: { headers: requestHeaders } });
  response.headers.set("Content-Security-Policy", csp);
  response.headers.set("X-Content-Type-Options", "nosniff");
  response.headers.set("X-Frame-Options", "DENY");
  response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
  response.headers.set("Permissions-Policy", "camera=(), microphone=(), geolocation=(), payment=(self)");
  response.headers.set("Strict-Transport-Security", "max-age=300; includeSubDomains");
  return response;
}

export const config = {
  matcher: ["/((?!api/csp-report|_next/static|_next/image|favicon.ico).*)"],
};

Se você usa Google Tag Manager, passe o nonce para o snippet ou componente. O bootstrap do GTM é JavaScript inline, e o próprio Google recomenda o uso de nonce. O AdSense também documenta strict CSP, pois os domínios de anúncios podem mudar com o tempo. Uma allowlist fixa pode quebrar receita depois.

Recebendo CSP reports

Report-Only precisa de um endpoint. Em Next.js, um Route Handler mínimo pode ser assim:

// app/api/csp-report/route.ts
import { NextRequest, NextResponse } from "next/server";

export async function POST(request: NextRequest) {
  const contentType = request.headers.get("content-type") ?? "";
  const body = await request.text();

  const isReport =
    contentType.includes("application/csp-report") ||
    contentType.includes("application/reports+json") ||
    body.includes("violated-directive");

  if (!isReport) {
    return NextResponse.json({ ok: false }, { status: 415 });
  }

  console.warn("csp-report", body.slice(0, 4000));
  return new NextResponse(null, { status: 204 });
}

Em produção, não grave URLs completas se parâmetros podem conter dados pessoais. Registre rota, diretiva violada, URI bloqueada, user agent, horário e contagem. report-uri é antigo, mas ainda é útil por compatibilidade. report-to pode ser complemento, não a única base.

Astro, Express e Cloudflare

Astro permite inserir headers em src/middleware.ts. Em sites majoritariamente estáticos, reduzir scripts inline costuma ser mais simples do que gerar nonces.

// src/middleware.ts
import { defineMiddleware } from "astro:middleware";

const securityHeaders: Record<string, string> = {
  "Content-Security-Policy-Report-Only": "default-src 'self'; script-src 'self' https://www.googletagmanager.com; img-src 'self' data: blob: https:; connect-src 'self' https://www.google-analytics.com; frame-src 'self' https://www.youtube-nocookie.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; report-uri /api/csp-report",
  "X-Content-Type-Options": "nosniff",
  "X-Frame-Options": "DENY",
  "Referrer-Policy": "strict-origin-when-cross-origin",
  "Permissions-Policy": "camera=(), microphone=(), geolocation=(), payment=(self)",
};

export const onRequest = defineMiddleware(async (_context, next) => {
  const response = await next();
  for (const [name, value] of Object.entries(securityHeaders)) {
    response.headers.set(name, value);
  }
  return response;
});

No Express, Helmet é a opção prática, mas CSP continua sendo específica da aplicação.

import crypto from "node:crypto";
import express from "express";
import helmet from "helmet";

const app = express();

app.use((req, res, next) => {
  res.locals.cspNonce = crypto.randomBytes(16).toString("base64");
  next();
});

app.use(helmet({
  contentSecurityPolicy: {
    useDefaults: false,
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`, "'strict-dynamic'", "https:", "http:"],
      imgSrc: ["'self'", "data:", "blob:", "https:"],
      connectSrc: ["'self'", "https://www.google-analytics.com"],
      objectSrc: ["'none'"],
      baseUri: ["'self'"],
      frameAncestors: ["'none'"],
      reportUri: ["/csp-report"],
    },
  },
  strictTransportSecurity: { maxAge: 300, includeSubDomains: true },
  referrerPolicy: { policy: "strict-origin-when-cross-origin" },
  xFrameOptions: { action: "deny" },
}));

Cloudflare Pages usa _headers para headers estáticos. Esse arquivo não cria nonces por request.

/*
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(self)
  Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://www.googletagmanager.com; img-src 'self' data: blob: https:; connect-src 'self' https://www.google-analytics.com; frame-src 'self' https://www.youtube-nocookie.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; report-uri /csp-report

Casos de uso e armadilhas

Um site de conteúdo com GA4, GTM, AdSense, fontes externas, YouTube e CDN de imagens precisa equilibrar segurança e receita. Use Report-Only antes de enforcement, valide se anúncios aparecem, se eventos de Analytics chegam e se imagens continuam carregando.

Uma área administrativa de SaaS deve ser mais restritiva. Menos scripts de terceiros, frame-ancestors 'none', object-src 'none', base-uri 'self' e form-action estreito são boas bases. SDKs de pagamento e chat devem existir apenas nas rotas necessárias.

Um widget incorporável precisa de política própria. Se clientes precisam inserir a página em iframe, X-Frame-Options: DENY quebra a funcionalidade. Separe headers por rota e defina origens confiáveis em frame-ancestors.

Verificação e resultado prático

Confira pelo menos home, login ou formulário, e uma rota de embed ou checkout.

curl -I https://example.com/
curl -I https://example.com/login
curl -I https://example.com/embed/widget

Depois use Security Headers para visão geral e CSP Evaluator para fragilidades da CSP. Nota alta é útil, mas não substitui teste de anúncio, Analytics, pagamento, imagem e iframe.

No teste preparado para este artigo, Report-Only foi o maior ganho. Ele separou problemas de nonce no GTM, connect-src no GA4, frame-src no YouTube e img-src no CDN. Com esses reports, Claude Code conseguiu propor política por rota, remoção de tags desnecessárias e aumento gradual de HSTS. Para aplicar isso em um projeto real, veja treinamento e consultoria Claude Code ou os templates e produtos ClaudeCodeLab e transforme a lista em regra de revisão no CLAUDE.md.

#Claude Code #security #HTTP headers #CSP #web development
Grátis

PDF grátis: cheatsheet do Claude Code

Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.

Cuidamos dos seus dados e não enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.