CSP report-only: testando políticas antes de aplicar

1. O que é o Modo Report-Only do CSP?

Content Security Policy (CSP) é uma camada de segurança que ajuda a detectar e mitigar ataques como Cross-Site Scripting (XSS) e data injection. O modo padrão (Content-Security-Policy) bloqueia recursos que violam a política definida. Já o modo report-only (Content-Security-Policy-Report-Only) não bloqueia nada — ele apenas gera relatórios de violação.

A diferença fundamental é:

  • Content-Security-Policy: bloqueia violações e envia relatórios (se configurado)
  • Content-Security-Policy-Report-Only: não bloqueia violações, apenas envia relatórios

Isso torna o modo report-only ideal para:
- Transição gradual de políticas em produção
- Validação de novas diretivas antes de aplicá-las
- Ambientes de staging e QA
- Identificação de dependências não documentadas de terceiros

2. Configurando o Header Content-Security-Policy-Report-Only

Sintaxe básica via cabeçalho HTTP

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-reports

Equivalente em meta tag HTML

<meta http-equiv="Content-Security-Policy-Report-Only" content="default-src 'self'; report-uri /csp-reports">

Diferenças práticas entre header e meta tag

Aspecto Header HTTP Meta Tag
Controle Servidor (mais seguro) Página HTML
Aplicação Todas as páginas Apenas a página atual
Suporte a report-to Sim Não
Prioridade Sobrescreve meta tag Ignorada se header existir

Recomendação: use sempre o cabeçalho HTTP quando possível, pois oferece mais controle e segurança.

3. Definindo o Endpoint de Reporte com report-uri e report-to

report-uri (legado)

Content-Security-Policy-Report-Only: default-src 'self'; report-uri https://meusite.com/csp-reports

report-to (moderno, baseado na Reporting API)

Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint

E no cabeçalho Reporting-Endpoints:

Reporting-Endpoints: csp-endpoint="https://meusite.com/reports"

Estrutura JSON de um relatório de violação CSP

{
  "csp-report": {
    "document-uri": "https://exemplo.com/pagina",
    "violated-directive": "script-src 'self'",
    "blocked-uri": "https://cdn.malicioso.com/script.js",
    "source-file": "https://exemplo.com/pagina",
    "line-number": 42,
    "column-number": 10,
    "effective-directive": "script-src",
    "original-policy": "default-src 'self'; report-uri /csp-reports"
  }
}

Endpoint simples em Node.js para receber relatórios

const express = require('express');
const app = express();

app.use(express.json({ type: 'application/csp-report' }));

app.post('/csp-reports', (req, res) => {
  const report = req.body['csp-report'];
  console.log('Violação CSP detectada:', {
    documento: report['document-uri'],
    diretiva: report['violated-directive'],
    recurso: report['blocked-uri']
  });
  res.status(204).end();
});

app.listen(3000);

4. Analisando Relatórios de Violação no Modo Report-Only

Campos essenciais do relatório

  • document-uri: URL da página onde a violação ocorreu
  • violated-directive: Diretiva CSP que foi violada
  • blocked-uri: URL do recurso que foi bloqueado
  • source-file: Arquivo JavaScript que causou a violação (se aplicável)
  • line-number e column-number: Localização exata no código

Exemplo de análise prática

Suponha que você receba este relatório:

{
  "csp-report": {
    "document-uri": "https://loja.com/produtos",
    "violated-directive": "img-src 'self'",
    "blocked-uri": "https://cdn.analytics.com/tracker.gif"
  }
}

Isso indica que sua página de produtos está tentando carregar imagens de um CDN de analytics não autorizado. Você precisará adicionar https://cdn.analytics.com à diretiva img-src.

Ferramentas de agregação

  • report-uri.io: serviço gerenciado para receber e visualizar relatórios CSP
  • Sentry: suporte a CSP reports com agregação e alertas
  • Dashboard customizado: usando banco de dados (ex.: MongoDB) e visualização (ex.: Grafana)

Como diferenciar falsos positivos

  • Extensões de navegador (ad-blockers, plugins) podem gerar relatórios falsos
  • Teste em múltiplos navegadores para confirmar violações reais
  • Verifique se o recurso bloqueado é essencial para o funcionamento da página

5. Iterando e Ajustando a Política com Base nos Relatórios

Estratégia de refinamento

  1. Comece restritivo: default-src 'self'
  2. Analise relatórios por 3-7 dias
  3. Adicione exceções apenas quando necessário

Exemplo prático: ajustando script-src

Relatório recebido:

{
  "csp-report": {
    "violated-directive": "script-src 'self'",
    "blocked-uri": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"
  }
}

Ajuste na política:

Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://cdnjs.cloudflare.com; report-uri /csp-reports

Identificando dependências de terceiros não documentadas

Relatórios podem revelar:
- Scripts de analytics que a equipe de marketing adicionou sem comunicar
- Fontes de terceiros carregadas por plugins ou widgets
- CDNs usadas por bibliotecas que você não sabia que estavam em uso

6. Transição do Modo Report-Only para o Modo Enforcement

Critérios para considerar uma política "madura"

  • Zero violações legítimas por pelo menos 7 dias consecutivos
  • Todos os recursos essenciais estão explicitamente permitidos
  • Testes em múltiplos navegadores não mostram quebras
  • Equipe de desenvolvimento validou que a política não afeta funcionalidades

Troca do cabeçalho

Antes (report-only):

Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://cdnjs.cloudflare.com; report-uri /csp-reports

Depois (enforcement):

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdnjs.cloudflare.com; report-uri /csp-reports

Manutenção contínua

Mesmo no modo enforcement, mantenha um endpoint de reporte ativo. Isso permite:
- Detectar novas violações causadas por mudanças no código
- Identificar tentativas de ataque (ex.: injeção de scripts)
- Monitorar a saúde da política ao longo do tempo

7. Boas Práticas e Armadilhas Comuns

Evitar sobrecarga de relatórios

  • Amostragem: configure seu servidor para processar apenas 10% dos relatórios
  • Limites de taxa: rejeite requisições excessivas do mesmo IP
  • Filtragem: ignore relatórios de extensões de navegador conhecidas

Cuidado com políticas muito restritivas

Políticas excessivamente restritivas podem quebrar:
- Botões de compartilhamento social
- Players de vídeo incorporados
- Widgets de chat ao vivo
- Mapas interativos

Testar em múltiplos navegadores

Cada navegador implementa CSP com pequenas diferenças:

  • Chrome: suporte completo, incluindo report-to
  • Firefox: bom suporte, mas pode diferir em diretivas específicas
  • Safari: suporte mais limitado, especialmente para report-to

Checklist de boas práticas

1. Inicie sempre com Content-Security-Policy-Report-Only
2. Configure um endpoint de reporte funcional
3. Analise relatórios por pelo menos uma semana
4. Documente cada exceção adicionada à política
5. Teste em Chrome, Firefox e Safari
6. Mantenha o endpoint de reporte mesmo no modo enforcement
7. Revise a política a cada novo deploy ou mudança significativa

Referências