Use a API Reporting para monitorar violações de segurança, chamadas de API descontinuadas e muito mais.
Alguns erros ocorrem apenas na produção. Você não vai encontrá-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 no seu site, e os transmite para um endpoint especificado.
Ela permite que você declare o que você quer monitorar usando cabeçalhos HTTP e é operada pelo navegador.
Ao configurar a API Reporting, você tem a tranquilidade de saber que, quando os usuários encontrarem esses tipos de erros, você vai saber para corrigi-los.
Nesta postagem, explicamos o que essa API pode fazer e como usá-la. Vamos lá.
Demonstração e código
Confira a API Reporting em ação a partir do Chrome 96 e versões mais recentes (Chrome Beta ou Canary, a partir de outubro de 2021).
Visão geral
Vamos supor que seu site, site.example
, tenha uma Política de segurança de conteúdo e uma Política de documentos. Não sabe o que eles fazem? Tudo bem, você ainda será
capaz de 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 que sua base de código pode estar usando.
Para fazer 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 para o endpoint configurado para esse tipo de violação. Os relatórios são enviados fora de 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 desses endpoints e monitorar o que deu errado. Você já 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 a monitorar muitos tipos de avisos ou problemas interessantes que ocorrem no seu site:
Tipo de relatório | Exemplo de uma situação em que um relatório seria gerado |
---|---|
Violação da CSP (apenas nível 3) | Você definiu um Content-Security-Policy (CSP) em uma das suas páginas, mas ela está tentando carregar um script que não é permitido pelo 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 foi carregado 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 descontinuação | A página usa uma API descontinuada ou que será descontinuada. Ela é chamada diretamente ou por um script de terceiros de nível superior. |
Intervenção | A página está tentando fazer algo que o navegador decidiu 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 o qual o usuário ainda não interagiu. |
Acidente | O navegador falha enquanto o site está aberto. |
Relatórios
Como são os relatórios?
O navegador envia relatórios para o endpoint que você configurou. Ele envia solicitações assim:
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 disponíveis 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 no body de um relatório são determinados pelo type do relatório. ⚠️ Relatórios de tipos diferentes têm corpos diferentes.
Para conferir o corpo exato de cada tipo de relatório, acesse o endpoint de demonstração de relatórios e siga as instruções para gerar exemplos de relatórios. |
type |
Um tipo de relatório, por exemplo, csp-violation ou coep . |
url |
O endereço do documento ou do trabalhador em que 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 em que o relatório foi gerado. |
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 mais contexto sobre o relatório. Por exemplo, se a conta de um determinado usuário está gerando erros de forma consistente ou se uma determinada sequência de ações realizadas em outras páginas está gerando um relatório nessa página.
Quando e como o navegador envia relatórios?
Os relatórios são enviados fora da banda do seu site: o navegador controla quando eles são enviados para os endpoints configurados. Também não há como controlar quando o navegador envia relatórios. Ele captura, enfileira e os envia automaticamente em um momento adequado.
Isso significa que há pouca ou nenhuma preocupação de 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 um trabalho de prioridade mais alta ou se o usuário estiver em uma rede lenta e/ou congestionada no momento.
Problemas próprios ou de terceiros
Os relatórios gerados devido a violações ou descontinuações que ocorrem na sua página são enviados para os endpoints que você configurou. Isso inclui violações cometidas por scripts de terceiros executados na sua página.
As violações ou descontinuações que ocorrerem em um iframe de origem cruzada incorporado à sua página não serão informadas aos endpoints (pelo menos não por padrão). Um iframe pode configurar seus próprios relatórios e até mesmo informar ao serviço de relatórios do seu site, ou seja, o serviço de primeira parte, mas isso depende do site em que ele está inserido. Além disso, a maioria dos relatórios é gerada apenas se a política de uma página for violada e se as políticas da página e do iframe forem diferentes.
Exemplo com descontinuações
Suporte ao navegador
A tabela abaixo resume o suporte do navegador à API Reporting v1, que tem o
cabeçalho Reporting-Endpoints
. O suporte do navegador para a API Reporting v0 (cabeçalho Report-To
) é o mesmo, exceto por 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 saber mais.
Tipo de relatório | Chrome | Chrome para 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 só resume o suporte a report-to
com o novo cabeçalho Reporting-Endpoints
. Leia as dicas de migração de relatórios da CSP se quiser migrar para o Reporting-Endpoints
.
Como usar a API Reporting
Decidir para onde os relatórios devem ser enviados
Você tem duas opções:
- Envie relatórios para um serviço de coletor de relatórios atual.
- Enviar relatórios para um coletor de relatórios que você mesmo cria e opera.
Opção 1: use um serviço de coletor de relatórios
Alguns exemplos de serviços de coletor de relatórios são:
- report-uri (link em inglês)
- uriports (em inglês)
Se você souber de outras soluções, registre um problema para nos informar 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ório? Por exemplo, nem todas as soluções de endpoint de relatórios são compatíveis com relatórios COOP/COEP.
- Você se sente confortável em compartilhar algum dos 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 ser vazadas dessa forma. Se isso parecer muito arriscado para seu aplicativo, opere seu próprio endpoint de comunicação.
Opção 2: criar e operar seu próprio coletor de relatórios
Criar seu próprio servidor que recebe relatórios não é tão simples. Para começar, você pode bifurcar nosso código boilerplate leve. Ele foi criado com o Express e pode receber e mostrar relatórios.
Acesse o coletor de relatórios padrão.
Clique em Remixar para editar para tornar o projeto editável.
Agora você tem seu clone! Você pode personalizar o layout para seus próprios fins.
Se você não estiver usando o código boilerplate e estiver criando seu próprio servidor do zero:
- Verifique se há solicitações
POST
com umContent-Type
deapplication/reports+json
para reconhecer solicitações de relatórios enviadas pelo navegador ao endpoint. - Se o endpoint estiver em uma origem diferente do site, verifique se ele oferece suporte a solicitações de pré-lançamento do CORS.
Opção 3: combinar as opções 1 e 2
Talvez você queira que um provedor específico cuide de alguns tipos de relatórios, mas tenha 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, pode ser interessante
definir ambos Reporting-Endpoints
e Report-To
. Confira os detalhes no guia de migração. Especificamente, se você estiver usando relatórios de
violações de Content-Security-Policy
apenas pela 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
.
É possível definir endpoints nomeados diferentes para diferentes tipos de relatório, por exemplo, my-coop-endpoint
e my-csp-endpoint
. Com isso, você pode encaminhar relatórios para diferentes endpoints, dependendo do tipo deles.
Se você quiser receber relatórios de intervenção, descontinuação e/ou falha, 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 da sua decisão na etapa 1.
Um URL de endpoint:
- Precisa começar com uma barra (
/
). Não há suporte para caminhos relativos. - Pode ser de origem cruzada, mas, nesse caso, as credenciais não são enviadas com os relatórios.
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 um único endpoint em todas as políticas.
Onde definir o cabeçalho?
Na nova API Reporting, aquela abordada nesta postagem, os relatórios têm o 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 diferentes endpoints.
Para receber relatórios de violações ou descontinuações em qualquer página do site, defina o cabeçalho como um middleware em todas as respostas.
Confira um exemplo no 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 sobre o qual você quer 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 nas políticas.
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. Elas são geradas enquanto
um endpoint default
estiver configurado e forem enviados para o 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
Exemplo de código
Para ver tudo isso no contexto, veja abaixo um exemplo de servidor de nó que usa o Express e reúne todas as partes discutidas neste artigo. Ele mostra como configurar relatórios para vários tipos diferentes de relatório e exibe os resultados.
Depurar a configuração dos relatórios
Gerar relatórios intencionalmente
Ao configurar a API Reporting, você provavelmente vai precisar violar intencionalmente suas políticas para verificar se os relatórios são gerados e enviados conforme esperado. Para ver um exemplo de código que viola as políticas e faz outras coisas ruins que gerarão relatórios de todos os tipos, confira a demonstração.
Poupe tempo
Os relatórios podem ser enviados com atraso, cerca de um minuto, 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 essa 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:
- Usar o Chrome 96 ou mais recente (digite
chrome://version
no navegador para confirmar) - Digite ou cole
chrome://flags/#enable-experimental-web-platform-features
na barra de URL do Chrome. - Clique em Ativado.
- Reinicie o navegador.
- Abra o Chrome DevTools.
- No Chrome DevTools, abra as Configurações. Em "Experimentos", clique em Ativar o painel da API Reporting no painel do aplicativo.
- Recarregue o DevTools.
- 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 API de relatórios.
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 a denúncia. |
Queued |
O relatório foi gerado e o navegador não está tentando enviá-lo no momento. Um relatório aparece como Queued em um destes dois casos:
|
MarkedForRemoval |
Depois de tentar por um tempo (Queued ), o navegador para de tentar enviar o relatório e o remove da lista de relatórios a serem enviados. |
Os relatórios são removidos depois de um tempo, independentemente de terem sido enviados ou não.
Solução de problemas
Os relatórios não são gerados ou enviados conforme o esperado para o endpoint? Confira algumas dicas para resolver isso.
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 nesta lista:
- Verifique
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 solucionar isso é verificar o console do DevTools no Chrome: se um erro aparecer no console para a violação que você esperava, isso significa que sua política provavelmente está configurada corretamente. - Lembre-se de que apenas os relatórios que foram gerados para o documento no DevTools estão abertos vão aparecer
nessa lista. Por exemplo, se o
site1.example
do seu site incorporar um iframesite2.example
que viole uma política e, portanto, gere um relatório, esse relatório só vai aparecer no DevTools se você abrir o iframe na própria janela e abrir o DevTools para essa janela.
Os relatórios são gerados, mas não são enviados ou recebidos
E se você conseguir acessar um relatório no DevTools, mas o endpoint não o receber?
- Use atrasos curtos. Talvez você não consiga encontrar um relatório porque ele ainda não foi enviado.
Verifique a configuração do cabeçalho
Reporting-Endpoints
. Se houver um problema, um relatório que foi gerado corretamente não será enviado. No DevTools, o status do relatório vai permanecerQueued
(pode pular paraPending
e voltar rapidamente paraQueued
quando uma tentativa de envio for feita) neste caso. Alguns erros comuns que podem causar isso:O endpoint é usado, mas não está configurado. Exemplo:
Document-Policy: document-write=?0;report-to=endpoint-1; Reporting-Endpoints: default="https://reports.example/default"
O endpoint
default
está ausente. Alguns tipos de relatórios, como os de descontinuação e intervenção, só serão enviados para o endpoint chamadodefault
. Leia mais em Configurar o cabeçalho Reporting-Endpoints.Procure problemas na sintaxe dos cabeçalhos da política, como falta de aspas. Mais detalhes.
Verifique se o endpoint pode processar as solicitações recebidas.
Verifique se o endpoint oferece suporte a solicitações simuladas de CORS. Caso contrário, ela não vai receber relatórios.
Teste o comportamento do endpoint. Para fazer isso, em vez de gerar relatórios manualmente, você pode emular o navegador enviando às solicitações de endpoint que se parecem com o que o navegador enviaria. Execute o comando a seguir:
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 responderá com um código de resposta bem-sucedida (
200
ou outro código de resposta de sucesso2xx
). Se não responder, há um problema com a configuração.
Mecanismos de denúncia relacionados
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á corrompido ou bloqueado, mas você receberá
relatórios sobre o que poderia ter sido corrompido ou bloqueado.
ReportingObserver
A API JavaScript ReportingObserver
pode ajudar você
a observar os avisos do lado do cliente.
ReportingObserver
e o cabeçalho Reporting-Endpoints
geram relatórios que
parecem iguais, mas permitem casos de uso um pouco diferentes.
Use ReportingObserver
se:
- Você só quer monitorar descontinuações e/ou intervenções do navegador.
O
ReportingObserver
mostra alertas do lado do cliente, como descontinuações e intervenções do navegador. No entanto, ao contrário doReporting-Endpoints
, ele não captura outros tipos de relatórios, como CSP ou violações de COOP/COEP. - Você precisa reagir a essas violações em tempo real.
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 no lado do cliente:
ele pode ser usado mesmo que você não tenha controle sobre os cabeçalhos do lado do servidor e não possa
definir Reporting-Endpoints
.
Leitura adicional
- Guia de migração da API Reporting v0 para a v1
- ReportingObserver
- Especificação: API Reporting legada (v0)
- Especificação: nova API Reporting (v1)
Imagem principal de Nine Koepfer / @enka80 no Unsplash, editada. Agradecemos a Ian Clelland, Eiji Kitamura e Milica Mihajlija pelas avaliações e sugestões neste artigo.