Usa la API de Reporting para supervisar incumplimientos de seguridad, llamadas a APIs 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 los incumplimientos de seguridad o las llamadas a la API que están obsoletas y pronto lo estarán en todo tu sitio, y los transmite a un extremo que especificaste.
Te permite declarar lo que deseas supervisar con encabezados HTTP y el navegador lo opera.
Configurar la API de Informes te brinda la tranquilidad de saber que, cuando los usuarios experimenten este tipo de errores, lo sabrás y podrás corregirlos.
En esta entrada, se explica qué puede hacer esta API y cómo usarla. ¡Comencemos!
Descripción general
Supongamos que tu sitio, site.example, tiene una política de seguridad del contenido y una política de documentos. ¿No sabes qué hacen? No te preocupes, podrás entender este ejemplo.
Decides supervisar tu sitio para saber cuándo se incumplen estas políticas, pero también porque quieres estar al tanto de las APIs obsoletas o que pronto dejarán de estar disponibles que tu base de código pueda estar usando.
Para ello, configura un encabezado Reporting-Endpoints y asigna estos nombres de extremos con 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
Se produce un 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 Document-Policy y un informe de baja que registran estos problemas.
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 envía los informes fuera de banda por sí mismo (no tu servidor ni tu sitio).
El extremo o los extremos reciben estos informes.
Ahora puedes acceder a los informes sobre estos endpoints y supervisar qué salió mal. Ya puedes 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) | Configuraste una Content-Security-Policy (CSP) en una de tus páginas, pero la página intenta cargar una secuencia de comandos que no permite tu CSP. |
| Incumplimiento de 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 COEP | Configuraste un Cross-Origin-Embedder-Policy en una página, pero el documento incluye un iframe de origen cruzado que no habilitó la carga por parte de 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 impide el uso del micrófono y una secuencia de comandos que solicita entrada de audio. |
| Advertencia de baja | La página usa una API que está obsoleta o que estará obsoleta; la llama directamente o con una secuencia de comandos de terceros de nivel superior. |
| Intervención | La página intenta hacer algo que el navegador decide no aceptar 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 iframe de origen cruzado con el que el usuario aún no interactuó. |
| Choque | El navegador falla mientras tu sitio está abierto. |
Informes
¿Cómo son 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 |
Cantidad de milisegundos entre la marca de tiempo del informe y la hora actual. |
body |
Son los datos reales del informe, serializados en una cadena JSON. Los campos incluidos en el body de un informe se determinan según el type del informe. ⚠️ Los informes de diferentes tipos tienen diferentes cuerpos.
|
type |
Es un tipo de informe, por ejemplo, csp-violation o coep. |
url |
Es la dirección del documento o del trabajador desde el que 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 |
Es el encabezado User-Agent de la solicitud a partir de la cual se generó el informe. |
Informes con credenciales
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 genera errores de forma constante o si una secuencia de acciones determinada que se realiza en otras páginas genera 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, los pone en cola y los envía automáticamente en un momento adecuado.
Esto significa que no hay problemas de rendimiento cuando se usa la API de Reporting.
Los informes se envían con un retraso (de hasta un minuto) para aumentar las probabilidades de enviarlos en lotes. Esto ahorra ancho de banda para respetar la conexión de red del usuario, lo que es especialmente importante en dispositivos móviles. El navegador también puede retrasar la entrega si está ocupado procesando trabajo de mayor prioridad o si el usuario se encuentra en una red lenta o congestionada en ese momento.
Problemas propios y de terceros
Los informes que se generen debido a incumplimientos o bajas que ocurran en tu página se enviarán a los extremos que hayas configurado. Esto incluye los incumplimientos cometidos por secuencias de comandos de terceros que se ejecutan en tu página.
Las infracciones o las bajas que se produjeron 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 e incluso informar al servicio de informes de tu sitio, es decir, al de origen, pero eso depende del sitio enmarcado. También 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 bajas
Navegadores compatibles
En la siguiente tabla, se resume la compatibilidad del navegador con la API de Reporting v1, es decir, con el encabezado Reporting-Endpoints. La compatibilidad del navegador con la versión 0 de la API de Reporting (encabezado Report-To) es la misma, excepto por un tipo de informe: el registro de errores de red no se admite en la nueva API de Reporting. Consulta la guía de migración para obtener más detalles.
| Tipo de informe | Chrome | Chrome 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 y 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 la migración de informes de CSP si deseas 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 operes tú mismo
Opción 1: Usa un servicio de recopilación 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 los informes de COOP/COEP.
- ¿Te sientes cómodo compartiendo las URLs de tu aplicación con un recopilador de informes externo? Incluso si el navegador quita la información sensible de estas URLs, es posible que se filtre información sensible de esta manera. Si esto te parece demasiado riesgoso para tu aplicación, opera tu propio extremo de informes.
Opción 2: Compila y opera tu propio recopilador de informes
Crear tu propio servidor que reciba informes no es tan trivial. Para comenzar, puedes bifurcar nuestra plantilla ligera. Está compilado con Express y puede recibir y mostrar informes.
Cuando creas tu propio recopilador de informes, sucede lo siguiente:
- Verifica si hay solicitudes
POSTcon unContent-Typedeapplication/reports+jsonpara reconocer las solicitudes de informes que envía el navegador a tu extremo. - Si tu extremo se encuentra en un origen diferente al de tu sitio, asegúrate de que admita solicitudes de comprobación previa de CORS.
Opción 3: Combina las opciones 1 y 2
Es posible que desees permitir que un proveedor específico se encargue de algunos tipos de informes, pero tener 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 API de Reporting, puede ser conveniente establecer ambos Reporting-Endpoints y Report-To. Consulta los detalles en la guía de migración.
En particular, si utilizas informes sobre incumplimientos de Content-Security-Policy solo con 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 el nombre que elijas, como main-endpoint o endpoint-1.
Puedes decidir establecer diferentes extremos con nombre para diferentes tipos de informes, por ejemplo, my-coop-endpoint y my-csp-endpoint. Con esto, puedes enrutar los informes a diferentes extremos según su tipo.
Si quieres recibir informes de intervención, baja, falla o una combinación de estos, configura un extremo llamado default.
Si el encabezado Reporting-Endpoints no define ningún extremo default, no se enviarán los informes de este tipo (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 se debe configurar aquí depende de lo que decidiste en el paso 1.
Una URL de extremo:
- Debe comenzar con una barra (
/). No se admiten rutas relativas. - Puede ser de origen cruzado, pero, en ese caso, no se envían credenciales 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 solo extremo en todas las políticas.
¿Dónde se debe configurar el encabezado?
En la nueva API de Reporting, la que se aborda en esta publicación, los informes se limitan a 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 sobre incumplimientos o bajas en cualquier página de tu sitio, configura el encabezado como middleware en todas las respuestas.
Aquí tienes 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 desees recibir informes de incumplimiento.
El valor de report-to debe ser uno de los extremos con nombre que configuraste.
Puedes usar el mismo extremo para varias políticas o usar diferentes extremos en las distintas políticas.

report-to no es necesario para los informes de baja, intervención y fallas. Estos informes no están vinculados a ninguna política. Se generan siempre y cuando se configure un extremo default y se envíen 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
Depura la configuración de tus informes
Genera informes de forma intencional
Cuando configures la API de Reporting, es probable que debas incumplir intencionalmente tus políticas para verificar si los informes se generan y envían según lo previsto.
Ahorra tiempo
Los informes pueden enviarse con un retraso de aproximadamente un minuto, lo que es un tiempo largo cuando se depura. 😴 Por suerte, cuando depuras en Chrome, puedes usar la marca --short-reporting-delay para recibir informes en cuanto se generen.
Ejecuta este comando en tu terminal para activar esta marca:
YOUR_PATH/TO/EXECUTABLE/Chrome --short-reporting-delay
Usa Herramientas para desarrolladores
En Chrome, usa las Herramientas para desarrolladores para ver los informes que se enviaron o que se enviarán.
A partir de octubre de 2021, esta función es experimental. Para usarla, sigue estos pasos:
- Usar la versión 96 o una posterior de Chrome (para verificarlo, escribe
chrome://versionen el navegador) - Escribe o pega
chrome://flags/#enable-experimental-web-platform-featuresen la barra de direcciones 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 de la API de Reporting en el panel de la aplicación.
- Vuelve a cargar Herramientas para desarrolladores.
- Vuelve a cargar la página. Los informes que genere la página en la que estén abiertas las Herramientas para desarrolladores se mostrarán en el panel Aplicación de las Herramientas para desarrolladores de Chrome, en Reporting API.
Estado del informe
La columna Estado te indica si se envió un informe correctamente.
| Estado | Descripción |
|---|---|
Success |
El navegador envió el informe y el extremo respondió con un código de éxito (200 o algún otro código de respuesta de éxito 2xx). |
Pending |
El navegador está intentando enviar el informe. |
Queued |
El informe se generó y el navegador no intenta enviarlo. Un informe aparece como Queued en uno de estos dos casos:
|
MarkedForRemoval |
Después de varios reintentos (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 ni se envían a tu extremo como se espera? Estas son algunas sugerencias para solucionar el 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-toen tus políticas. Si se configura de forma incorrecta, no se generará un informe. Ve a Edita tus políticas para corregir este problema. Otra forma de solucionar este problema es verificar la consola de Herramientas para desarrolladores en Chrome: si aparece un error en la consola por el incumplimiento que esperabas, significa que tu política probablemente esté configurada correctamente. - Ten en cuenta que solo aparecerán en esta lista los informes que se generaron para el documento en el que se abrieron las Herramientas para desarrolladores. Un ejemplo: Si tu sitio
site1.exampleincorpora un iframesite2.exampleque incumple una política y, por lo tanto, genera un informe, este informe aparecerá en las Herramientas para desarrolladores solo si abres el iframe en su propia ventana y abres las Herramientas para desarrolladores para esa ventana.
Se generan los informes, pero no se envían ni se reciben
¿Qué sucede si puedes ver un informe en las Herramientas para desarrolladores, pero tu extremo no lo recibe?
- Asegúrate de usar retrasos cortos. Quizás 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 este caso, en Herramientas para desarrolladores, el estado del informe permanecerá comoQueued(es posible que cambie aPendingy, luego, vuelva rápidamente aQueuedcuando se realice un intento de entrega). Estos son algunos errores comunes que pueden causar este problema:Se usa el extremo, pero no se configura. Ejemplo:
Document-Policy: document-write=?0;report-to=endpoint-1; Reporting-Endpoints: default="https://reports.example/default"
Los informes de incumplimiento de Document-Policy se deben enviar a endpoint-1, pero este nombre de extremo no está configurado en Reporting-Endpoints.
Falta el extremo
default. Algunos tipos de informes, como los de baja y los de intervención, solo se enviarán al extremo llamadodefault. Obtén más información en Cómo configurar el encabezado Reporting-Endpoints.Busca problemas en la sintaxis de los encabezados de tus políticas, como comillas faltantes. Ver detalles.
Verifica que tu extremo pueda controlar las solicitudes entrantes.
Asegúrate de que tu extremo admita solicitudes de comprobación previa de CORS. Si no es así, no podrá recibir avisos.
Prueba el comportamiento de tu extremo. Para ello, en lugar de generar informes de forma manual, puedes emular el navegador enviando a tu extremo solicitudes que parezcan las 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_ENDPOINTTu extremo debe responder con un código de éxito (
200o algún otro código de respuesta de éxito2xx). Si no lo hace, hay un problema con su configuración.
Mecanismos de informes relacionados
Solo informes
Los encabezados de política -Report-Only y el Reporting-Endpoints funcionan en conjunto.
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 incumplan 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 incumplan estas políticas.
Si bien los informes se envían en ambos casos, los encabezados -Report-Only no aplican las políticas: nada se interrumpirá ni se bloqueará, pero recibirás informes sobre lo que se habría interrumpido o bloqueado.
ReportingObserver
La API de JavaScript de ReportingObserver puede ayudarte a observar las advertencias del cliente.
ReportingObserver y el encabezado Reporting-Endpoints generan informes que se ven iguales, pero habilitan casos de uso ligeramente diferentes.
Usa ReportingObserver en los siguientes casos:
- Solo quieres supervisar las bajas o las intervenciones del navegador.
ReportingObservermuestra advertencias del cliente, como las bajas y las intervenciones del navegador, pero, a diferencia deReporting-Endpoints, no captura ningún otro tipo de informes, como los incumplimientos de la CSP o de COOP/COEP. - Debes reaccionar a estos incumplimientos en tiempo real.
ReportingObserverpermite adjuntar una devolución de llamada a un evento de incumplimiento. - Quieres adjuntar información adicional a un informe para ayudar con la depuración, usando 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 establecer Reporting-Endpoints.
Lecturas adicionales
- Guía de migración de la versión 0 a la versión 1 de la API de Reporting
- ReportingObserver
- Especificación: API de Reporting heredada (v0)
- Especificación: Nueva API de Reporting (v1)
Imagen de encabezado de Nine Koepfer / @enka80 en Unsplash, editada. Muchas gracias a Ian Clelland, Eiji Kitamura y Milica Mihajlija por sus revisiones y sugerencias sobre este documento.