Usa la API de Reporting para supervisar incumplimientos de seguridad, llamadas a la API obsoletas y mucho más.
Algunos errores solo ocurren en producción. No los verás de forma local ni durante el desarrollo, ya que los usuarios reales, las redes reales y los dispositivos reales cambian el juego. La API de Reporting ayuda a detectar algunos de estos errores, como violaciones de seguridad o llamadas a la API obsoletas y que pronto dejarán de estar disponibles, en tu sitio y los transmite a un extremo que especificaste.
Te permite declarar lo que quieres supervisar mediante encabezados HTTP, y lo opera el navegador.
Configurar la API de Reporting te brinda la tranquilidad de saber que, cuando los usuarios experimentan estos tipos de errores, lo sabrás para que puedas corregirlos.
En esta publicación, se describe lo que puede hacer esta API y cómo usarla. ¡Comencemos!
Demostración y código
Consulta la API de Reporting en acción a partir de Chrome 96 y versiones posteriores (Chrome Beta o Canary, a partir de octubre de 2021).
Descripción general
Supongamos que tu sitio, site.example
, tiene una Content-Security-Policy y una Document-Policy. ¿No sabes qué hacen? Está bien, todavía podrás
comprender este ejemplo.
Decides supervisar tu sitio para saber cuándo se incumplen estas políticas, pero también porque quieres tener en cuenta las APIs que dejaron de estar disponibles o que pronto dejarán de estarlo que podría estar usando tu base de código.
Para hacerlo, configura un encabezado Reporting-Endpoints
y asigna estos nombres de extremos a través de la directiva report-to
en tus políticas cuando sea necesario.
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
Ocurre algo imprevisto y se incumplen estas políticas para algunos de tus usuarios.
Ejemplos de incumplimientos
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
, cargado 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;
El navegador genera un informe de incumplimiento de CSP, un informe de incumplimiento de la política de documentos y un informe de baja que capturan estos problemas.
Luego, con una breve demora (hasta un minuto), el navegador envía los informes al extremo que se configuró para este tipo de incumplimiento. El navegador es el que envía los informes fuera de banda (no tu servidor ni tu sitio).
Los extremos reciben estos informes.
Ahora puedes acceder a los informes en estos extremos y supervisar qué salió mal. Ya está todo listo para comenzar a solucionar el problema que afecta a tus usuarios.
Informe de ejemplo
{
"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 y tipos de informes
La API de Reporting se puede configurar para ayudarte a supervisar muchos tipos de advertencias o problemas interesantes que ocurren en tu sitio:
Tipo de informe | Ejemplo de una situación en la que se generaría un informe |
---|---|
Incumplimiento de la CSP (solo nivel 3) | Estableciste un Content-Security-Policy (CSP) en una de tus páginas, pero la página intenta cargar una secuencia de comandos que tu CSP no permite. |
Incumplimiento de la COOP | Estableciste un Cross-Origin-Opener-Policy en una página, pero una ventana de origen cruzado intenta interactuar directamente con el documento. |
Incumplimiento de la COEP | Estableciste un Cross-Origin-Embedder-Policy en una página, pero el documento incluye un iframe de origen cruzado que no aceptó que lo carguen documentos de origen cruzado. |
Incumplimiento de la Política de Documentos | La página tiene una política de documentos que impide el uso de document.write , pero una secuencia de comandos intenta llamar a document.write . |
Incumplimiento de la política de permisos | La página tiene una política de permisos que evita el uso del micrófono y una secuencia de comandos que solicita una entrada de audio. |
Advertencia de baja | La página está usando una API que está obsoleta o dejará de estar disponible; la llama directamente o a través de una secuencia de comandos externa de nivel superior. |
Intervención | La página intenta hacer algo que el navegador decide no cumplir por motivos de seguridad, rendimiento o experiencia del usuario. Ejemplo en Chrome: la página usa document.write en redes lentas o llama a navigator.vibrate en un marco de origen cruzado con el que el usuario aún no interactuó. |
Choque | El navegador falla mientras tu sitio está abierto. |
Informes
¿Cómo se ven los informes?
El navegador envía informes al extremo que configuraste. Envía solicitudes que se ven de la siguiente manera:
POST
Content-Type: application/reports+json
La carga útil de estas solicitudes es una lista de informes.
Ejemplo de lista de informes
[
{
"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"
}
]
Estos son los datos que puedes encontrar en cada uno de estos informes:
Campo | Descripción |
---|---|
age |
Es la cantidad de milisegundos entre la marca de tiempo del informe y la hora actual. |
body |
Los datos reales del informe, serializados en una cadena JSON. Los campos contenidos en el body de un informe se determinan según el type del informe. ⚠️ Los informes de diferentes tipos tienen cuerpos diferentes.
Para ver el cuerpo exacto de cada tipo de informe, consulta el extremo de informes de demostración y sigue las instrucciones para generar informes de ejemplo. |
type |
Un tipo de informe, por ejemplo, csp-violation o coep . |
url |
Es la dirección del documento o del trabajador a partir del cual se generó el informe. Los datos sensibles, como el nombre de usuario, la contraseña y el fragmento, se quitan de esta URL. |
user_agent |
El encabezado User-Agent de la solicitud a partir de la cual se generó el informe |
Informes acreditados
Los extremos de informes que tienen el mismo origen que la página que genera el informe reciben las credenciales (cookies) en las solicitudes que contienen los informes.
Las credenciales pueden proporcionar contexto adicional útil sobre el informe, por ejemplo, si la cuenta de un usuario determinado activa errores de forma coherente o si una determinada secuencia de acciones realizadas en otras páginas activa un informe en esta página.
¿Cuándo y cómo envía informes el navegador?
Los informes se entregan fuera de banda desde tu sitio: el navegador controla cuándo se envían a los extremos configurados. Tampoco hay forma de controlar cuándo el navegador envía informes; los captura, pone en cola y envía automáticamente en un momento adecuado.
Esto significa que hay poco o ningún problema de rendimiento cuando se usa la API de Reporting.
Los informes se envían con una demora (de hasta un minuto) para aumentar las posibilidades de enviar informes en lotes. Esto ahorra ancho de banda para respetar la conexión de red del usuario, lo que es muy importante en dispositivos móviles. El navegador también puede retrasar la entrega si está ocupado procesando tareas de mayor prioridad o si el usuario se encuentra en una red lenta o congestionada en ese momento.
Problemas de terceros y propios
Los informes que se generen debido a incumplimientos o baja de elementos en tu página se enviarán a los extremos que hayas configurado. Esto incluye incumplimientos cometidos por secuencias de comandos de terceros que se ejecutan en tu página.
Los incumplimientos o las bajas que se produzcan en un iframe de origen cruzado incorporado en tu página no se informarán a tus extremos (al menos, no de forma predeterminada). Un iframe podría configurar sus propios informes y, además, informar al servicio de informes de tu sitio (es decir, del propietario), pero eso depende del sitio enmarcado. Además, ten en cuenta que la mayoría de los informes se generan solo si se incumple la política de una página y que las políticas de tu página y las del iframe son diferentes.
Ejemplo con baja
Navegadores compatibles
En la siguiente tabla, se resume la compatibilidad de los navegadores con la API de Reporting v1, es decir, con el encabezado Reporting-Endpoints
. La compatibilidad del navegador con la API de Reporting v0 (encabezado Report-To
) es la misma, excepto por un tipo de informe: el registro de errores de red no es compatible con la nueva API de Reporting.
Para obtener más detalles, consulta la guía de migración.
Tipo de informe | Chrome | Chrome para iOS | Safari | Firefox | Edge |
---|---|---|---|---|---|
Incumplimiento de CSP (solo nivel 3)* | ✔ Sí | ✔ Sí | ✔ Sí | ✘ No | ✔ Sí |
Registro de errores de red | ✘ No | ✘ No | ✘ No | ✘ No | ✘ No |
Incumplimiento de COOP/COEP | ✔ Sí | ✘ No | ✔ Sí | ✘ No | ✔ Sí |
Todos los demás tipos: Incumplimiento de la política de documentos, baja, intervención, falla | ✔ Sí | ✘ No | ✘ No | ✘ No | ✔ Sí |
En esta tabla, solo se resume la compatibilidad con report-to
con el nuevo encabezado Reporting-Endpoints
. Lee las sugerencias para migrar los informes de CSP si quieres migrar a Reporting-Endpoints
.
Usa la API de Reporting
Decide dónde se deben enviar los informes
Tienes estas dos opciones:
- Enviar informes a un servicio de recopilación de informes existente
- Enviar informes a un recopilador de informes que crees y administres
Opción 1: Usa un servicio de recopilador de informes existente
Estos son algunos ejemplos de servicios de recopilación de informes:
Si conoces otras soluciones, abre un problema para informarnos al respecto y actualizaremos esta publicación.
Además del precio, ten en cuenta los siguientes puntos cuando selecciones un recopilador de informes: 🧐
- ¿Este recopilador admite todos los tipos de informes? Por ejemplo, no todas las soluciones de extremos de informes admiten informes COOP/COEP.
- ¿Te sientes cómodo compartiendo alguna de las URLs de tu aplicación con un recopilador de informes de terceros? Incluso si el navegador quita la información sensible de estas URLs, es posible que se filtre de esta manera. Si esto suena demasiado riesgoso para tu aplicación, opera tu propio extremo de informes.
Opción 2: Crea y opera tu propio recopilador de informes
Crear tu propio servidor que reciba informes no es tan sencillo. Para comenzar, puedes bifurcar nuestro código estándar ligero. Se compiló con Express y puede recibir y mostrar informes.
Haz clic en Remix para editar para que el proyecto sea editable.
¡Ya tienes tu clon! Puedes personalizarlo según tus propios fines.
Si no usas el modelo de texto y compilas tu propio servidor desde cero, haz lo siguiente:
- Verifica si hay solicitudes
POST
con unContent-Type
deapplication/reports+json
para reconocer las solicitudes de informes que el navegador envía a tu extremo. - Si tu extremo se encuentra en un origen diferente al de tu sitio, asegúrate de que admita las solicitudes de comprobación previa de CORS.
Opción 3: Combina las opciones 1 y 2
Es posible que desees que un proveedor específico se encargue de algunos tipos de informes, pero que tengas una solución interna para otros.
En este caso, configura varios extremos de la siguiente manera:
Reporting-Endpoints: endpoint-1="https://reports-collector.example", endpoint-2="https://my-custom-endpoint.example"
Configura el encabezado Reporting-Endpoints
Establece un encabezado de respuesta Reporting-Endpoints
. Su valor debe ser uno o una serie de pares clave-valor separados por comas:
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
Si migras de la API de Reporting heredada a la nueva, tiene sentido configurar tanto Reporting-Endpoints
como Report-To
. Consulta los detalles en la guía de migración. En particular, si usas informes de incumplimientos de Content-Security-Policy
solo a través de la directiva report-uri
, consulta los pasos de migración para los informes de CSP.
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
Report-To: ...
Claves (nombres de extremos)
Cada clave puede ser un nombre que elijas, como main-endpoint
o endpoint-1
.
Puedes establecer diferentes extremos nombrados para diferentes tipos de informes, por ejemplo, my-coop-endpoint
, my-csp-endpoint
. Con esto, puedes desviar informes a diferentes extremos según su tipo.
Si deseas recibir informes de intervenciones, bajas o fallas, configura un extremo llamado default
.
Si el encabezado Reporting-Endpoints
no define ningún extremo default
, los informes de este tipo no se enviarán (aunque se generarán).
Valores (URLs)
Cada valor es una URL de tu elección a la que se enviarán los informes. La URL que debes configurar aquí depende de lo que decidiste en el paso 1.
Una URL de extremo:
- Debe comenzar con una barra (
/
). No se admiten rutas de acceso relativas. - Pueden ser de varios orígenes, pero, en ese caso, las credenciales no se envían con los informes.
Ejemplos
Reporting-Endpoints: my-coop-endpoint="https://reports.example/coop", my-csp-endpoint="https://reports.example/csp", default="https://reports.example/default"
Luego, puedes usar cada extremo con nombre en la política correspondiente o usar un extremo en todas las políticas.
¿Dónde se debe configurar el encabezado?
En la nueva API de Reporting, la que se describe en esta
publicación, los informes se segmentan en documentos. Esto significa que, para un origen determinado, diferentes documentos, como site.example/page1
y site.example/page2
, pueden enviar informes a diferentes extremos.
Para recibir informes de incumplimientos o baja de elementos en cualquier página de tu sitio, configura el encabezado como un middleware en todas las respuestas.
Este es un ejemplo en 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();
});
Edita tus políticas
Ahora que el encabezado Reporting-Endpoints
está configurado, agrega una directiva report-to
a cada encabezado de política para el que deseas recibir informes de incumplimiento. El valor de report-to
debe ser uno de los extremos con nombre que configuraste.
Puedes usar el extremo múltiple para varias políticas o usar extremos diferentes en las políticas.
No se necesita report-to
para los informes de baja, intervención y accidente automovilístico. Estos informes no están vinculados a ninguna política. Se generan siempre que se configure un extremo default
y se envían a este extremo default
.
Ejemplo
# 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
Ejemplo de código
Para ver todo esto en contexto, a continuación, se muestra un ejemplo de servidor de Node que usa Express y reúne todos los elementos que se analizaron en este artículo. Aquí se indica cómo configurar los informes para varios tipos de informes diferentes y se muestran los resultados.
Cómo depurar la configuración de informes
Generar informes de manera intencional
Cuando configures la API de Reporting, es probable que debas incumplir de forma intencional tus políticas para verificar si los informes se generan y se envían como se espera. Para ver un código de ejemplo que incumple las políticas y realiza otras acciones que generarán informes de todo tipo, consulta la demo.
Ahorra tiempo
Es posible que los informes se envíen con un retraso de aproximadamente un minuto, lo que es un tiempo largo durante la depuración. 😴 Por suerte, cuando depuras en Chrome, puedes usar la marca --short-reporting-delay
para recibir informes en cuanto se generan.
Ejecuta este comando en la terminal para activar la marca:
YOUR_PATH/TO/EXECUTABLE/Chrome --short-reporting-delay
Cómo usar las Herramientas para desarrolladores
En Chrome, usa las Herramientas para desarrolladores para ver los informes que se enviaron o se enviarán.
A partir de octubre de 2021, esta función es experimental. Para usarla, sigue estos pasos:
- Usas Chrome 96 y versiones posteriores (para comprobarlo, escribe
chrome://version
en el navegador). - Escribe o pega
chrome://flags/#enable-experimental-web-platform-features
en la barra de URL de Chrome. - Haz clic en Habilitado.
- Reinicia el navegador.
- Abra las Herramientas para desarrolladores de Chrome.
- En las Herramientas para desarrolladores de Chrome, abre la configuración. En Experimentos, haz clic en Habilitar el panel API de informes en el panel Aplicación.
- Vuelve a cargar Herramientas para desarrolladores.
- Vuelve a cargar la página. Los informes generados por la página en la que se abrieron las Herramientas para desarrolladores se mostrarán en el panel Application de las Herramientas para desarrolladores de Chrome, en Reporting API.
Estado del informe
La columna Estado te indica si se envió correctamente un aviso.
Estado | Descripción |
---|---|
Success |
El navegador envió el informe y el extremo respondió con un código de éxito (200 o cualquier otro código de respuesta de éxito 2xx ). |
Pending |
El navegador está intentando enviar el informe. |
Queued |
Se generó el informe y, en este momento, el navegador no intenta enviarlo. Un informe aparece como Queued en uno de estos dos casos:
|
MarkedForRemoval |
Después de reintentarlo durante un tiempo (Queued ), el navegador dejó de intentar enviar el informe y pronto lo quitará de su lista de informes para enviar. |
Los informes se quitan después de un tiempo, independientemente de si se envían correctamente o no.
Solución de problemas
¿Los informes no se generan o no se envían como se espera a tu extremo? Aquí encontrarás algunas sugerencias para solucionar este problema.
No se generan informes
Los informes que aparecen en Herramientas para desarrolladores se generaron correctamente. Si el informe que esperas no aparece en esta lista, haz lo siguiente:
- Verifica
report-to
en tus políticas. Si está mal configurado, no se generará un informe. Ve a Editar tus políticas para solucionar este problema. Otra forma de solucionar este problema es verificar la consola de DevTools en Chrome: si aparece un error en la consola por el incumplimiento que esperabas, significa que es probable que tu política esté configurada correctamente. - Ten en cuenta que solo los informes que se generaron para el documento en el que las Herramientas para desarrolladores están abiertos se mostrarán en esta lista. Un ejemplo: si tu sitio
site1.example
incorpora un iframesite2.example
que incumple una política y, por lo tanto, genera un informe, este informe aparecerá en DevTools solo si abres el iframe en su propia ventana y abres DevTools para esa ventana.
Los informes se generan, pero no se envían o no se reciben
¿Qué sucede si puedes ver un informe en DevTools, pero tu extremo no lo recibe?
- Asegúrate de usar demoras cortas. Es posible que no puedas ver un informe porque aún no se envió.
Verifica la configuración del encabezado
Reporting-Endpoints
. Si hay un problema, no se enviará un informe que se haya generado correctamente. En las Herramientas para desarrolladores, el estado del informe seguirá siendoQueued
(puede saltar aPending
y, luego, volver rápidamente aQueued
cuando se realice un intento de entrega) en este caso. Estos son algunos errores comunes que pueden causar este problema:El extremo se usa, pero no está configurado. Ejemplo:
Document-Policy: document-write=?0;report-to=endpoint-1; Reporting-Endpoints: default="https://reports.example/default"
Falta el extremo
default
. Algunos tipos de informes, como los informes de baja y de intervención, solo se enviarán al extremo llamadodefault
. Obtén más información en Configura el encabezado Reporting-Endpoints.Busca problemas en la sintaxis de los encabezados de tu política, como comillas faltantes. Consulta los detalles.
Verifica que tu extremo pueda controlar las solicitudes entrantes.
Asegúrate de que tu extremo admita solicitudes de comprobación previa de CORS. De lo contrario, no podrá recibir informes.
Prueba el comportamiento de tu extremo. Para ello, en lugar de generar informes manualmente, puedes emular el navegador enviando a tu extremo solicitudes que parezcan lo que enviaría el navegador. Ejecuta lo siguiente:
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
El extremo debe responder con un código de éxito (
200
o cualquier otro código de respuesta de éxito2xx
). Si no es así, significa que hay un problema con su configuración.
Mecanismos de denuncia relacionados
Solo informes
Los encabezados de la política -Report-Only
y Reporting-Endpoints
funcionan juntos.
Los extremos configurados en Reporting-Endpoints
y especificados en el campo report-to
de Content-Security-Policy
, Cross-Origin-Embedder-Policy
y Cross-Origin-Opener-Policy
recibirán informes cuando se infrinjan estas políticas.
Los extremos configurados en Reporting-Endpoints
también se pueden especificar en el campo report-to
de Content-Security-Policy-Report-Only
, Cross-Origin-Embedder-Policy-Report-Only
y Cross-Origin-Opener-Policy-Report-Only
.
También recibirán informes cuando se infrinjan estas políticas.
Si bien los informes se envían en ambos casos, los encabezados -Report-Only
no aplican las políticas: no se romperá ni se bloqueará nada, pero recibirás informes de lo que se habría roto o bloqueado.
ReportingObserver
La API de JavaScript de ReportingObserver
puede ayudarte a observar advertencias del cliente.
ReportingObserver
y el encabezado Reporting-Endpoints
generan informes que se ven igual, pero permiten casos de uso ligeramente diferentes.
Usa ReportingObserver
en los siguientes casos:
- Solo quieres supervisar las bajas o las intervenciones del navegador.
ReportingObserver
muestra advertencias del cliente, como baja de versiones y intervenciones del navegador, pero, a diferencia deReporting-Endpoints
, no captura ningún otro tipo de informe, como incumplimientos de CSP o COOP/COEP. - Debes reaccionar a estos incumplimientos en tiempo real.
ReportingObserver
permite adjuntar una devolución de llamada a un evento de incumplimiento. - Quieres adjuntar información adicional a un informe para ayudar a depurar, mediante la devolución de llamada personalizada.
Otra diferencia es que ReportingObserver
solo se configura del lado del cliente: puedes usarlo incluso si no tienes control sobre los encabezados del servidor y no puedes configurar Reporting-Endpoints
.
Lecturas adicionales
- Guía de migración de la API de Reporting v0 a v1
- ReportingObserver
- Especificación: API de informes heredada (versión 0)
- Especificación: nueva API de Reporting (v1)
Imagen hero de Nine Koepfer / @enka80 en Unsplash, editada. Muchas gracias a Ian Clelland, Eiji Kitamura y Milica Mihajlija por sus comentarios y sugerencias sobre este artículo.