Monitorar seu aplicativo da Web com a API Reporting

Use a API Reporting para monitorar violações de segurança, chamadas de API descontinuadas e muito mais.

Maud Nalpas
Maud Nalpas

Alguns erros só ocorrem em produção. Você não vai vê-los localmente ou durante o desenvolvimento porque usuários reais, redes reais e dispositivos reais mudam o jogo. A API Reporting ajuda a detectar alguns desses erros, como violações de segurança ou chamadas de API descontinuadas e que serão descontinuadas em breve em todo o site, e os transmite para um endpoint especificado.

Ele permite declarar o que você quer monitorar usando cabeçalhos HTTP e é operado pelo navegador.

Configurar a API Reporting dá a você a tranquilidade de saber que, quando os usuários enfrentarem esses tipos de erros, você será informado e poderá corrigi-los.

Esta postagem aborda o que essa API pode fazer e como usá-la. Vamos lá!

Visão geral

Diagrama que resume as etapas abaixo, desde a geração até o acesso do desenvolvedor ao relatório
Como os relatórios são gerados e enviados.

Vamos supor que seu site, site.example, tenha uma política de segurança de conteúdo e uma política de documento. Não sabe o que eles fazem? Não tem problema, você ainda vai conseguir entender este exemplo.

Você decide monitorar seu site para saber quando essas políticas são violadas, mas também porque quer ficar de olho nas APIs descontinuadas ou que serão descontinuadas em breve que sua base de código pode estar usando.

Para isso, configure um cabeçalho Reporting-Endpoints e mapeie esses nomes de endpoint usando a diretiva report-to nas políticas, quando necessário.

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the `default` endpoint

Algo imprevisto acontece, e essas políticas são violadas para alguns dos seus usuários.

Exemplos de violações

index.html

<script src="script.js"></script>
<!-- CSP VIOLATION: Try to load a script that's forbidden as per the Content-Security-Policy -->
<script src="https://example.com/script.js"></script>

script.js, carregado por index.html

// DOCUMENT-POLICY VIOLATION: Attempt to use document.write despite the document policy
try {
  document.write('<h1>hi</h1>');
} catch (e) {
  console.log(e);
}
// DEPRECATION: Call a deprecated API
const webkitStorageInfo = window.webkitStorageInfo;

O navegador gera um relatório de violação da CSP, um relatório de violação da política de documentos e um relatório de descontinuação que capturam esses problemas.

Com um pequeno atraso (até um minuto), o navegador envia os relatórios ao endpoint configurado para esse tipo de violação. Os relatórios são enviados fora da banda pelo próprio navegador (não pelo seu servidor nem pelo seu site).

Os endpoints recebem esses relatórios.

Agora você pode acessar os relatórios nesses endpoints e monitorar o que deu errado. Agora você pode começar a resolver o problema que está afetando seus usuários.

Exemplo de relatório

{
  "age": 2,
  "body": {
    "blockedURL": "https://site2.example/script.js",
    "disposition": "enforce",
    "documentURL": "https://site.example",
    "effectiveDirective": "script-src-elem",
    "originalPolicy": "script-src 'self'; object-src 'none'; report-to main-endpoint;",
    "referrer": "https://site.example",
    "sample": "",
    "statusCode": 200
  },
  "type": "csp-violation",
  "url": "https://site.example",
  "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
}

Casos de uso e tipos de relatórios

A API Reporting pode ser configurada para ajudar você a monitorar vários tipos de avisos ou problemas interessantes que acontecem em todo o site:

Tipo de relatório Exemplo de uma situação em que um relatório seria gerado
Violação da CSP (somente nível 3) Você definiu uma Content-Security-Policy (CSP) em uma das suas páginas, mas ela está tentando carregar um script que não é permitido pela CSP.
Violação da COOP Você definiu um Cross-Origin-Opener-Policy em uma página, mas uma janela de origem cruzada está tentando interagir diretamente com o documento.
Violação da COEP Você definiu um Cross-Origin-Embedder-Policy em uma página, mas o documento inclui um iframe entre origens que não ativou o carregamento por documentos entre origens.
Violação da política de documentos A página tem uma política de documentos que impede o uso de document.write, mas um script tenta chamar document.write.
Violação da política de permissões A página tem uma política de permissões que impede o uso do microfone e um script que solicita entrada de áudio.
Aviso de suspensão de uso A página está usando uma API descontinuada ou que será descontinuada. Ela a chama diretamente ou usando um script de terceiros de nível superior.
Intervenção A página está tentando fazer algo que o navegador decide não aceitar por motivos de segurança, desempenho ou experiência do usuário. Exemplo no Chrome: a página usa document.write em redes lentas ou chama navigator.vibrate em um frame de origem cruzada com que o usuário ainda não interagiu.
Acidente O navegador falha enquanto seu site está aberto.

Relatórios

Como são os relatórios?

O navegador envia relatórios para o endpoint configurado. Ele envia solicitações que têm esta aparência:

POST
Content-Type: application/reports+json

O payload dessas solicitações é uma lista de relatórios.

Exemplo de lista de relatórios

[
  {
    "age": 420,
    "body": {
      "columnNumber": 12,
      "disposition": "enforce",
      "lineNumber": 11,
      "message": "Document policy violation: document-write is not allowed in this document.",
      "policyId": "document-write",
      "sourceFile": "https://site.example/script.js"
    },
    "type": "document-policy-violation",
    "url": "https://site.example/",
    "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
  },
  {
    "age": 510,
    "body": {
      "blockedURL": "https://site.example/img.jpg",
      "destination": "image",
      "disposition": "enforce",
      "type": "corp"
    },
    "type": "coep",
    "url": "https://dummy.example/",
    "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
  }
]

Confira os dados que você pode encontrar em cada um desses relatórios:

Campo Descrição
age O número de milissegundos entre o carimbo de data/hora do relatório e o horário atual.
body Os dados reais do relatório, serializados em uma string JSON. Os campos contidos em um body de relatório são determinados pelo type do relatório. ⚠️ Relatórios de tipos diferentes têm corpos diferentes.
type Um tipo de relatório, por exemplo, csp-violation ou coep.
url O endereço do documento ou do worker de onde o relatório foi gerado. Dados sensíveis, como nome de usuário, senha e fragmento, são removidos desse URL.
user_agent O cabeçalho User-Agent da solicitação que gerou o relatório.

Relatórios com credenciais

Os endpoints de relatórios que têm a mesma origem da página que gera o relatório recebem as credenciais (cookies) nas solicitações que contêm os relatórios.

As credenciais podem fornecer um contexto adicional útil sobre o relatório. Por exemplo, se a conta de um determinado usuário está acionando erros de forma consistente ou se uma determinada sequência de ações realizadas em outras páginas está acionando um relatório nesta página.

Quando e como o navegador envia relatórios?

Os relatórios são entregues fora da banda do seu site: o navegador controla quando eles são enviados aos endpoints configurados. Também não é possível controlar quando o navegador envia relatórios. Ele captura, coloca em fila e envia automaticamente em um momento adequado.

Isso significa que há pouca ou nenhuma preocupação com o desempenho ao usar a API Reporting.

Os relatórios são enviados com um atraso (até um minuto) para aumentar as chances de envio em lotes. Isso economiza largura de banda para respeitar a conexão de rede do usuário, o que é especialmente importante em dispositivos móveis. O navegador também pode atrasar a entrega se estiver ocupado processando trabalhos de maior prioridade ou se o usuário estiver em uma rede lenta ou congestionada no momento.

Problemas de terceiros e próprios

Os relatórios gerados devido a violações ou descontinuações na sua página serão enviados aos endpoints configurados. Isso inclui violações cometidas por scripts de terceiros em execução na sua página.

Violações ou descontinuações que ocorreram em um iframe de origem cruzada incorporado na sua página não serão informadas aos seus endpoints (pelo menos não por padrão). Um iframe pode configurar a própria geração de relatórios e até mesmo informar ao serviço de geração de relatórios do seu site, ou seja, do proprietário. No entanto, isso depende do site em frame. Além disso, a maioria dos relatórios é gerada apenas se a política de uma página for violada, e as políticas da sua página e do iframe são diferentes.

Exemplo com descontinuações

Se o cabeçalho &quot;Reporting-Endpoints&quot; estiver configurado na sua página, a API descontinuada chamada por scripts de terceiros em execução na página será informada ao seu endpoint. A API descontinuada chamada por um iframe incorporado na sua página não será informada ao endpoint. Um relatório de suspensão de uso só será gerado se o servidor do iframe tiver configurado Reporting-Endpoints, e ele será enviado para qualquer endpoint que o servidor do iframe tiver configurado.
Se o cabeçalho "Reporting-Endpoints" estiver configurado na sua página: a API descontinuada chamada por scripts de terceiros em execução na sua página será informada ao seu endpoint. A API descontinuada chamada por um iframe incorporado à sua página não será informada ao endpoint. Um relatório de suspensão de uso só será gerado se o servidor do iframe tiver configurado Reporting-Endpoints, e ele será enviado para qualquer endpoint que o servidor do iframe tiver configurado.

Suporte ao navegador

A tabela a seguir resume a compatibilidade do navegador com a API Reporting v1, ou seja, com o cabeçalho Reporting-Endpoints. O suporte do navegador para a API Reporting v0 (cabeçalho Report-To) é o mesmo, exceto para um tipo de relatório: o registro de erros de rede não é compatível com a nova API Reporting. Leia o guia de migração para mais detalhes.

Tipo de relatório Chrome Chrome iOS Safari Firefox Edge
Violação da CSP (somente nível 3)* ✔ Sim ✔ Sim ✔ Sim ✘ Não ✔ Sim
Registro de erros de rede ✘ Não ✘ Não ✘ Não ✘ Não ✘ Não
Violação de COOP/COEP ✔ Sim ✘ Não ✔ Sim ✘ Não ✔ Sim
Todos os outros tipos: violação da política de documentos, descontinuação, intervenção, falha ✔ Sim ✘ Não ✘ Não ✘ Não ✔ Sim

Esta tabela resume apenas o suporte para report-to com o novo cabeçalho Reporting-Endpoints. Leia as dicas de migração de relatórios da CSP se quiser migrar para Reporting-Endpoints.

Como usar a API Reporting

Decidir para onde os relatórios devem ser enviados

Você tem duas opções:

  • Enviar relatórios para um serviço de coleta de relatórios.
  • Enviar relatórios para um coletor de relatórios criado e operado por você.

Opção 1: usar um serviço de coleta de relatórios

Alguns exemplos de serviços de coleta de relatórios:

Se você conhece outras soluções, abra um problema para nos avisar, e vamos atualizar esta postagem.

Além do preço, considere os seguintes pontos ao selecionar um coletor de relatórios: 🧐

  • Esse coletor é compatível com todos os tipos de relatórios? Por exemplo, nem todas as soluções de endpoint de relatórios são compatíveis com relatórios COOP/COEP.
  • Você se sente à vontade para compartilhar os URLs do seu aplicativo com um coletor de relatórios de terceiros? Mesmo que o navegador remova informações sensíveis desses URLs, elas podem vazar dessa forma. Se isso parecer muito arriscado para seu aplicativo, opere seu próprio endpoint de relatórios.

Opção 2: criar e operar seu próprio coletor de relatórios

Criar seu próprio servidor para receber relatórios não é tão simples. Para começar, crie um fork do nosso boilerplate leve. Ele foi criado com o Express e pode receber e mostrar relatórios.

Ao criar seu próprio coletor de relatórios:

  • Verifique se há solicitações POST com um Content-Type de application/reports+json para reconhecer solicitações de relatórios enviadas pelo navegador ao seu endpoint.
  • Se o endpoint estiver em uma origem diferente do seu site, verifique se ele aceita solicitações de pré-lançamento do CORS.

Opção 3: combinar as opções 1 e 2

Talvez você queira deixar um provedor específico cuidar de alguns tipos de relatórios, mas ter uma solução interna para outros.

Nesse caso, defina vários endpoints da seguinte maneira:

Reporting-Endpoints: endpoint-1="https://reports-collector.example", endpoint-2="https://my-custom-endpoint.example"

Configurar o cabeçalho Reporting-Endpoints

Defina um cabeçalho de resposta Reporting-Endpoints. O valor precisa ser um ou uma série de pares de chave-valor separados por vírgulas:

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"

Se você estiver migrando da API Reporting legada para a nova, talvez seja interessante definir os dois Reporting-Endpoints e Report-To. Confira mais detalhes no guia de migração. Em especial, se você estiver usando relatórios de violações de Content-Security-Policy com a diretiva report-uri, confira as etapas de migração para relatórios de CSP.

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
Report-To: ...

Chaves (nomes de endpoints)

Cada chave pode ser um nome de sua escolha, como main-endpoint ou endpoint-1. Você pode definir endpoints nomeados diferentes para tipos de relatórios diferentes, por exemplo, my-coop-endpoint e my-csp-endpoint. Assim, você pode encaminhar relatórios para diferentes endpoints, dependendo do tipo deles.

Se você quiser receber relatórios de intervenção, suspensão de uso, falha ou uma combinação deles, defina um endpoint chamado default.

Se o cabeçalho Reporting-Endpoints não definir um endpoint default, os relatórios desse tipo não serão enviados, embora sejam gerados.

Valores (URLs)

Cada valor é um URL de sua escolha, para onde os relatórios serão enviados. O URL a ser definido aqui depende do que você decidiu na etapa 1.

Um URL de endpoint:

Exemplos

Reporting-Endpoints: my-coop-endpoint="https://reports.example/coop", my-csp-endpoint="https://reports.example/csp", default="https://reports.example/default"

Em seguida, use cada endpoint nomeado na política apropriada ou use um único endpoint em todas as políticas.

Onde definir o cabeçalho?

Na nova API Reporting, que é o assunto deste post, os relatórios são definidos no escopo de documentos. Isso significa que, para uma determinada origem, diferentes documentos, como site.example/page1 e site.example/page2, podem enviar relatórios para endpoints diferentes.

Para receber um relatório sobre violações ou descontinuações em qualquer página do seu site, defina o cabeçalho como um middleware em todas as respostas.

Confira um exemplo em Express:

const REPORTING_ENDPOINT_BASE = 'https://report.example';
const REPORTING_ENDPOINT_MAIN = `${REPORTING_ENDPOINT_BASE}/main`;
const REPORTING_ENDPOINT_DEFAULT = `${REPORTING_ENDPOINT_BASE}/default`;

app.use(function (request, response, next) {
  // Set up the Reporting API
  response.set(
    'Reporting-Endpoints',
    `main-endpoint="${REPORTING_ENDPOINT_MAIN}", default="${REPORTING_ENDPOINT_DEFAULT}"`,
  );
  next();
});

Editar suas políticas

Agora que o cabeçalho Reporting-Endpoints está configurado, adicione uma diretiva report-to a cada cabeçalho de política para receber relatórios de violação. O valor de report-to precisa ser um dos endpoints nomeados que você configurou.

É possível usar o endpoint múltiplo para várias políticas ou usar endpoints diferentes em várias políticas.

Para cada política, o valor de &quot;report-to&quot; precisa ser um dos endpoints nomeados que você configurou.

O report-to não é necessário para relatórios de descontinuação, intervenção e falha. Esses relatórios não estão vinculados a nenhuma política. Eles são gerados desde que um endpoint default esteja configurado e sejam enviados a esse endpoint default.

Exemplo

# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0;report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the default endpoint

Depurar a configuração de relatórios

Gerar relatórios intencionalmente

Ao configurar a API Reporting, talvez seja necessário violar intencionalmente suas políticas para verificar se os relatórios são gerados e enviados conforme o esperado.

Poupe tempo

Os relatórios podem ser enviados com um atraso de cerca de um minuto, o que é um tempo longo ao depurar. 😴 Felizmente, ao depurar no Chrome, você pode usar a flag --short-reporting-delay para receber relatórios assim que eles forem gerados.

Execute este comando no terminal para ativar a flag:

YOUR_PATH/TO/EXECUTABLE/Chrome --short-reporting-delay

Usar o DevTools

No Chrome, use o DevTools para ver os relatórios que foram ou serão enviados.

A partir de outubro de 2021, esse recurso é experimental. Para usar, siga estas etapas:

  1. Use o Chrome 96 ou mais recente. Para verificar, digite chrome://version no navegador.
  2. Digite ou cole chrome://flags/#enable-experimental-web-platform-features na barra de endereço do Chrome.
  3. Clique em Ativado.
  4. Reinicie o navegador.
  5. Abra o Chrome DevTools.
  6. No Chrome DevTools, abra as Configurações. Em "Experimentos", clique em Ativar o painel da API Reporting no painel "Aplicativo".
  7. Recarregue o DevTools.
  8. Atualize a página. Os relatórios gerados pela página em que o DevTools está aberto serão listados no painel Application do Chrome DevTools, em Reporting API.
Captura de tela do DevTools listando os relatórios
O Chrome DevTools mostra os relatórios gerados na sua página e o status deles.

Status do relatório

A coluna Status informa se um relatório foi enviado.

Status Descrição
Success O navegador enviou o relatório, e o endpoint respondeu com um código de sucesso (200 ou outro código de resposta de sucesso 2xx).
Pending O navegador está tentando enviar o relatório.
Queued O relatório foi gerado e o navegador não está tentando enviá-lo. Um relatório aparece como Queued em um destes dois casos:
  • O relatório é novo, e o navegador está aguardando para ver se mais relatórios chegam antes de tentar enviá-lo.
  • O relatório não é novo. O navegador já tentou enviar o relatório e não conseguiu. Ele está aguardando antes de tentar de novo.
MarkedForRemoval Depois de tentar novamente por um tempo (Queued), o navegador parou de tentar enviar o relatório e logo o removerá da lista de relatórios a serem enviados.

Os relatórios são removidos depois de um tempo, sejam eles enviados ou não.

Solução de problemas

Os relatórios não são gerados ou enviados conforme o esperado para seu endpoint? Confira algumas dicas para resolver esse problema.

Os relatórios não são gerados

Os relatórios que aparecem no DevTools foram gerados corretamente. Se o relatório esperado não aparecer na lista:

  • Confira report-to nas suas políticas. Se isso estiver configurado incorretamente, um relatório não será gerado. Acesse Editar suas políticas para corrigir isso. Outra maneira de resolver esse problema é verificar o console do DevTools no Chrome: se um erro aparecer no console para a violação esperada, isso significa que sua política provavelmente está configurada corretamente.
  • Apenas os relatórios gerados para o documento em que o DevTools está aberto vão aparecer nessa lista. Por exemplo, se o site site1.example incorporar um iframe site2.example que viola uma política e gera um relatório, ele só vai aparecer no DevTools se você abrir o iframe em uma janela própria e abrir o DevTools para essa janela.

Os relatórios são gerados, mas não enviados ou recebidos

E se você conseguir ver um relatório no DevTools, mas seu endpoint não o receber?

  • Use atrasos curtos. Talvez o motivo de você não conseguir ver um relatório seja porque ele ainda não foi enviado.
  • Verifique a configuração do cabeçalho Reporting-Endpoints. Se houver um problema com ele, um relatório gerado corretamente não será enviado. No DevTools, o status do relatório vai permanecer Queued (pode pular para Pending e depois voltar rapidamente para Queued quando uma tentativa de entrega é feita) nesse caso. Alguns erros comuns que podem causar isso:

  • O endpoint é usado, mas não está configurado. Exemplo:

Código com um erro
 Document-Policy: document-write=?0;report-to=endpoint-1;
 Reporting-Endpoints: default="https://reports.example/default"

Os relatórios de violação da política de documentos devem ser enviados para endpoint-1, mas esse nome de endpoint não está configurado em Reporting-Endpoints.

  • O endpoint default está ausente. Alguns tipos de relatórios, como os de descontinuação e intervenção, serão enviados apenas para o endpoint chamado default. Leia mais em Configurar o cabeçalho Reporting-Endpoints.

  • Procure problemas na sintaxe dos cabeçalhos de política, como aspas ausentes. Confira detalhes.

  • Verifique se o endpoint pode processar solicitações recebidas.

    • Verifique se o endpoint aceita solicitações simuladas de CORS. Se não, ele não poderá receber relatórios.

    • Teste o comportamento do endpoint. Para isso, em vez de gerar relatórios manualmente, emule o navegador enviando ao seu endpoint solicitações que parecem o que o navegador enviaria. Execute o seguinte:

    curl --header "Content-Type: application/reports+json" \
      --request POST \
      --data '[{"age":420,"body":{"columnNumber":12,"disposition":"enforce","lineNumber":11,"message":"Document policy violation: document-write is not allowed in this document.","policyId":"document-write","sourceFile":"https://dummy.example/script.js"},"type":"document-policy-violation","url":"https://dummy.example/","user_agent":"xxx"},{"age":510,"body":{"blockedURL":"https://dummy.example/img.jpg","destination":"image","disposition":"enforce","type":"corp"},"type":"coep","url":"https://dummy.example/","user_agent":"xxx"}]' \
      YOUR_ENDPOINT
    

    Seu endpoint precisa responder com um código de sucesso (200 ou outro código de resposta de sucesso 2xx). Se isso não acontecer, há um problema na configuração dele.

Somente relatórios

Os cabeçalhos de política -Report-Only e o Reporting-Endpoints funcionam juntos.

Os endpoints configurados em Reporting-Endpoints e especificados no campo report-to de Content-Security-Policy, Cross-Origin-Embedder-Policy e Cross-Origin-Opener-Policy vão receber relatórios quando essas políticas forem violadas.

Os endpoints configurados em Reporting-Endpoints também podem ser especificados no campo report-to de Content-Security-Policy-Report-Only, Cross-Origin-Embedder-Policy-Report-Only e Cross-Origin-Opener-Policy-Report-Only. Eles também vão receber relatórios quando essas políticas forem violadas.

Embora os relatórios sejam enviados nos dois casos, os cabeçalhos -Report-Only não aplicam as políticas: nada será interrompido ou bloqueado, mas você vai receber relatórios sobre o que seria interrompido ou bloqueado.

ReportingObserver

A API ReportingObserver JavaScript pode ajudar você a observar avisos do lado do cliente.

ReportingObserver e o cabeçalho Reporting-Endpoints geram relatórios que parecem iguais, mas permitem casos de uso ligeiramente diferentes.

Use ReportingObserver se:

  • Você só quer monitorar descontinuações ou intervenções do navegador. O ReportingObserver mostra avisos do lado do cliente, como descontinuações e intervenções do navegador, mas, ao contrário do Reporting-Endpoints, não captura outros tipos de relatórios, como violações de CSP ou COOP/COEP.
  • Você precisa reagir a essas violações em tempo real. O ReportingObserver permite anexar um callback a um evento de violação.
  • Você quer anexar mais informações a um relatório para ajudar na depuração usando o callback personalizado.

Outra diferença é que o ReportingObserver é configurado apenas do lado do cliente: você pode usá-lo mesmo que não tenha controle sobre os cabeçalhos do lado do servidor e não possa definir Reporting-Endpoints.

Leitura adicional

Imagem principal de Nine Koepfer / @enka80 no Unsplash, editada. Agradecemos a Ian Clelland, Eiji Kitamura e Milica Mihajlija pelas revisões e sugestões neste documento.