Aísla tu sitio web de otros orígenes con COOP y COEP

Usa COOP y COEP para configurar un entorno aislado de origen cruzado y habilitar funciones potentes, como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() y un temporizador de alta resolución con mejor precisión.

Publicado: 13 de abril de 2020; última actualización: 21 de junio de 2022

En este documento, se muestra cómo usar COOP y COEP. Puedes obtener más información sobre por qué esto es importante en Haz que tu sitio web tenga "aislamiento de origen cruzado" con COOP y COEP.

Algunas APIs web aumentan el riesgo de ataques de canal lateral, como Spectre. Para mitigar ese riesgo, los navegadores ofrecen un entorno aislado basado en la aceptación, llamado aislado de origen cruzado. Con un estado aislado de origen cruzado, la página web podrá usar funciones privilegiadas, incluidas las siguientes:

API Descripción
SharedArrayBuffer Es obligatorio para los subprocesos de WebAssembly. Esta función está disponible a partir de Chrome 88 para Android. La versión para computadoras está habilitada de forma predeterminada con la ayuda del aislamiento de sitios, pero requerirá el estado aislado de origen cruzado y se inhabilitará de forma predeterminada en Chrome 92.
performance.measureUserAgentSpecificMemory() Disponible a partir de Chrome 89.
performance.now(), performance.timeOrigin Está disponible en muchos navegadores, con una resolución limitada a 100 microsegundos o más. Con el aislamiento de origen cruzado, la resolución puede ser de 5 microsegundos o más.
Funciones que estarán disponibles detrás del estado aislado de origen cruzado.

El estado aislado de origen cruzado también evita las modificaciones de document.domain. (Poder alterar document.domain permite la comunicación entre documentos del mismo sitio y se consideró un vacío legal en la política del mismo origen).

Para habilitar un estado aislado de origen cruzado, debes enviar los siguientes encabezados HTTP en el documento principal:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

Estos encabezados indican al navegador que bloquee la carga de recursos o iframes que no hayan habilitado la carga por parte de documentos de origen cruzado, y evitan que las ventanas de origen cruzado interactúen directamente con tu documento. Esto también significa que esos recursos que se cargan de origen cruzado requieren habilitaciones.

Para determinar si una página web está en un estado aislado de origen cruzado, examina self.crossOriginIsolated.

Glosario

En este documento, se usan muchos términos con nombres y abreviaturas similares. Para aclarar, creamos un miniglosario:

Cómo hacer que tu sitio web tenga aislamiento de origen cruzado

1. Establece Cross-Origin-Opener-Policy: same-origin en el documento de nivel superior

Si habilitas COOP: same-origin en un documento de nivel superior, las ventanas con el mismo origen y las ventanas abiertas desde el documento tendrán un grupo de contexto de navegación independiente, a menos que estén en el mismo origen con la misma configuración de COOP. Por lo tanto, se aplica el aislamiento para las ventanas abiertas y se inhabilita la comunicación mutua entre ambas ventanas.

Un grupo de contexto de navegación es un conjunto de ventanas que pueden hacerse referencia entre sí. Por ejemplo, un documento de nivel superior y sus documentos secundarios incorporados con <iframe>. Si un sitio web (https://a.example) abre una ventana de diálogo (https://b.example), la ventana de apertura y la ventana de diálogo comparten el mismo contexto de navegación, por lo que tienen acceso entre sí con las APIs de DOM, como window.opener.

Ilustración que representa el grupo de contenido de navegación con el usuario interactuando con los elementos de la página.

Puedes verificar si el abridor de ventanas y su openee están en grupos de contexto de navegación separados desde Herramientas para desarrolladores.

2. Habilita CORP o CORS en los recursos

Asegúrate de que todos los recursos de la página se carguen con encabezados HTTP de CORP o CORS. Este paso es obligatorio para el paso cuatro, que consiste en habilitar la COEP.

Esto es lo que debes hacer, según la naturaleza del recurso:

  • Si se espera que el recurso se cargue solo desde el mismo origen, establece el encabezado Cross-Origin-Resource-Policy: same-origin.
  • Si se espera que el recurso se cargue solo desde el mismo sitio, pero con un origen cruzado, establece el encabezado Cross-Origin-Resource-Policy: same-site.
  • Si el recurso se carga desde uno o más orígenes cruzados bajo tu control, establece el encabezado Cross-Origin-Resource-Policy: cross-origin si es posible.
  • Para los recursos de origen cruzado sobre los que no tienes control, haz lo siguiente:
    • Usa el atributo crossorigin en la etiqueta HTML de carga si el recurso se entrega con CORS. (Por ejemplo, <img src="***" crossorigin>).
    • Pídele al propietario del recurso que admita CORS o CORP.
  • Para los iframes, sigue los mismos principios y establece el atributo Cross-Origin-Resource-Policy: cross-origin (o same-site, same-origin según el contexto).
  • Las secuencias de comandos cargadas con un WebWorker se deben entregar desde el mismo origen, por lo que no necesitas encabezados CORP ni CORS.
  • Para un documento o un trabajador que se entrega con COEP: require-corp, los recursos secundarios de origen cruzado que se cargan sin CORS deben establecer el encabezado Cross-Origin-Resource-Policy: cross-origin para habilitar la incorporación. Por ejemplo, esto se aplica a <script>, importScripts, <link>, <video>, <iframe>, etcétera.

Aislamiento en iframes

Puedes habilitar el aislamiento de origen cruzado en un documento incorporado en un iframe aplicando la política de permisos allow="cross-origin-isolated" a la etiqueta <iframe> y cumpliendo con estas condiciones. Toda la cadena de documentos, incluidos los marcos superiores y secundarios, también debe estar aislada de origen cruzado.

3. Usa el encabezado HTTP de solo informes de COEP para evaluar los recursos incorporados

Antes de habilitar por completo la COEP, puedes realizar una ejecución de prueba con el encabezado Cross-Origin-Embedder-Policy-Report-Only para examinar si la política realmente funciona. Recibirás informes sin bloquear el contenido incorporado.

Aplica esto de forma recurrente a todos los documentos, incluidos el documento de nivel superior, los iframes y las secuencias de comandos de trabajadores. Para obtener información sobre el encabezado HTTP de solo informes, consulta Observa los problemas con la API de Reporting.

4. Habilita la COEP

Este paso solo se puede realizar una vez que hayas comprobado que los recursos tengan habilitados CORP o CORS.

Una vez que hayas confirmado que todo funciona y que todos los recursos se pueden cargar correctamente, cambia el encabezado Cross-Origin-Embedder-Policy-Report-Only por el encabezado Cross-Origin-Embedder-Policy con el mismo valor para todos los documentos, incluidos los que están incorporados con iframes y secuencias de comandos de trabajadores.

Determina si el aislamiento se realizó correctamente

La propiedad self.crossOriginIsolated devuelve true cuando la página web se encuentra en un estado aislado de origen cruzado y todos los recursos y las ventanas están aislados dentro del mismo grupo de contexto de navegación. Puedes usar esta API para determinar si aislaste correctamente el grupo de contexto de navegación y obtuviste acceso a funciones como performance.measureUserAgentSpecificMemory().

Depurar problemas

Es posible que tengas problemas con COOP y COEP. Puedes usar las herramientas para desarrolladores del navegador o la API de informes para depurar.

Depura con las Herramientas para desarrolladores de Chrome

En el caso de los recursos que se renderizan en la pantalla, como las imágenes, es bastante fácil detectar problemas de COEP, ya que la solicitud se bloquea y la página debería indicar que falta una imagen. Sin embargo, en el caso de los recursos que no necesariamente tienen un impacto visual, como las secuencias de comandos o los estilos, los problemas de COEP pueden pasar desapercibidos. Para esos casos, usa el panel de redes de las Herramientas para desarrolladores.

Si hay un problema con la COEP, deberías ver (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep) en la columna Estado.

Problemas de COEP en la columna Estado del panel de red.

Luego, puedes hacer clic en la entrada para ver más detalles.

Los detalles del problema de COEP se muestran en la pestaña Encabezados después de hacer clic en un recurso de red en el panel Red.

También puedes determinar el estado de los iframes y las ventanas de diálogo a través del panel Aplicación. Ve a la sección "Frames" en el lado izquierdo y expande "top" para ver el desglose de la estructura de recursos.

Puedes verificar el estado del iframe, como la disponibilidad de SharedArrayBuffer, etc.

Inspector de iframe de las Herramientas para desarrolladores de Chrome.

También puedes verificar el estado de las ventanas de diálogo, por ejemplo, si están aisladas de origen cruzado.

Inspector de ventanas de diálogo de las Herramientas para desarrolladores de Chrome

Observa los problemas con la API de Reporting

La API de Reporting es otro mecanismo que te permite detectar varios problemas. Puedes configurar la API de Reporting para indicarle al navegador de tus usuarios que envíe un informe cada vez que la COEP bloquee la carga de un recurso o la COOP aísle una ventana de diálogo. Chrome admite la API de Reporting desde la versión 69 para una variedad de usos, incluidos COEP y COOP.

Obtén información para configurar la API de Reporting y un servidor para recibir informes.

Ejemplo de informe de COEP

Un ejemplo de carga útil de un informe de COEP cuando se bloquea un recurso de origen cruzado se ve de la siguiente manera:

[{
  "age": 25101,
  "body": {
    "blocked-url": "https://third-party-test.example.org/check.svg?",
    "blockedURL": "https://third-party-test.example.org/check.svg?",
    "destination": "image",
    "disposition": "enforce",
    "type": "corp"
  },
  "type": "coep",
  "url": "https://cross-origin-isolation.example.com/?coep=require-corp&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36"
}]

Ejemplo de informe de COOP

Un ejemplo de carga útil de un informe de COOP cuando se abre un diálogo aislado se ve de la siguiente manera:

[{
  "age": 7,
  "body": {
    "disposition": "enforce",
    "effectivePolicy": "same-origin",
    "nextResponseURL": "https://third-party-test.example.org/popup?report-only&coop=same-origin&",
    "type": "navigation-from-response"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

Cuando diferentes grupos de contexto de navegación intentan acceder entre sí (solo en el modo "solo informes"), COOP también envía un informe. Por ejemplo, un informe cuando se intenta postMessage() se vería de la siguiente manera:

[{
  "age": 51785,
  "body": {
    "columnNumber": 18,
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "lineNumber": 83,
    "property": "postMessage",
    "sourceFile": "https://cross-origin-isolation.example.com/popup.js",
    "type": "access-from-coop-page-to-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
},
{
  "age": 51785,
  "body": {
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "property": "postMessage",
    "type": "access-to-coop-page-from-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

Conclusiones

Usa una combinación de encabezados HTTP de COOP y COEP para que una página web adopte un estado especial aislado de origen cruzado. Puedes examinar self.crossOriginIsolated para determinar si una página web está en un estado aislado de origen cruzado.

Mantendremos esta publicación actualizada a medida que se lancen nuevas funciones para este estado aislado de origen cruzado y se realicen más mejoras en las Herramientas para desarrolladores en relación con COOP y COEP.

Recursos

Actualizaciones de documentos

  • 21 de junio de 2022: Las secuencias de comandos de trabajadores también necesitan atención cuando se habilita el aislamiento de origen cruzado. Se agregaron algunas explicaciones.
  • 5 de agosto de 2021: Se mencionó la API de JS Self-Profiling como una de las APIs que requieren aislamiento de origen cruzado, pero se quitó para reflejar el cambio de dirección reciente.
  • 6 de mayo de 2021: En función de los comentarios y los problemas informados, decidimos ajustar el cronograma para que el uso de SharedArrayBuffer en sitios aislados de origen cruzado se restrinja en Chrome M92.
  • 16 de abril de 2021: Se agregaron notas sobre el modo sin credenciales de COEP y same-origin-allow-popups de COOP para que sea una condición relajada para el aislamiento de origen cruzado.
  • 5 de marzo de 2021: Se quitaron las limitaciones para SharedArrayBuffer, performance.measureUserAgentSpecificMemory() y las funciones de depuración, que ahora están completamente habilitadas en Chrome 89. Se agregaron las próximas funciones, performance.now() y performance.timeOrigin, que tendrán mayor precisión.
  • 19 de febrero de 2021: Se agregó una nota sobre la política de funciones allow="cross-origin-isolated" y la funcionalidad de depuración en las Herramientas para desarrolladores.
  • 15 de octubre de 2020: self.crossOriginIsolated está disponible a partir de Chrome 87. Para reflejar eso, document.domain es inmutable cuando self.crossOriginIsolated devuelve true. performance.measureUserAgentSpecificMemory() finalizará su prueba de origen y se habilitará de forma predeterminada en Chrome 89. SharedArrayBuffer en Chrome para Android estará disponible a partir de Chrome 88.