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.

Fecha de publicación: 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 Cómo hacer que tu sitio web esté "aislado 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 opción de participació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. Está disponible desde Android Chrome 88. La versión para computadoras de escritorio 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 desde Chrome 89.
performance.now(), performance.timeOrigin 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 impide las modificaciones de document.domain. (La capacidad de alterar document.domain permite la comunicación entre documentos del mismo sitio y se consideró una laguna en la política de 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 le indican al navegador que bloquee la carga de recursos o iframes que no hayan habilitado la carga de documentos de origen cruzado y eviten que las ventanas de origen cruzado interactúen directamente con tu documento. Esto también significa que los recursos que se cargan de origen cruzado requieren la opción de participación.

Puedes determinar si una página web está en un estado aislado de origen cruzado examinando examinando self.crossOriginIsolated.

Glosario

En este documento, se usa mucha terminología abreviada y con nombres similares. Para aclarar, seleccionamos un miniglosario:

Cómo hacer que tu sitio web esté aislado 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 que se abren desde el documento tienen 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 hacer 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 un usuario que interactúa 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 independientes 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 habilita 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 Cross-Origin-Resource-Policy: same-origin encabezado.
  • Si se espera que el recurso se cargue solo desde el mismo sitio, pero de origen cruzado, establece el encabezado Cross-Origin-Resource-Policy: same-site.
  • Si el recurso se carga desde orígenes cruzados bajo tu control, establece el Cross-Origin-Resource-Policy: cross-origin encabezado 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 Cross-Origin-Resource-Policy: cross-origin (o same-site, same-origin según el contexto).
  • Las secuencias de comandos cargadas con un WebWorker deben entregarse desde el mismo origen, por lo que no necesitas encabezados CORP o CORS.
  • Para un documento o un trabajador que se entrega con COEP: require-corp, los subrecursos de origen cruzado cargados 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 si aplicas la política de permisos allow="cross-origin-isolated" a la <iframe> etiqueta y cumples 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 COEP Report-Only para evaluar los recursos incorporados

Antes de habilitar por completo COEP, puedes hacer 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 recursiva a todos los documentos, incluidos el documento de nivel superior, los iframes y las secuencias de comandos de trabajador. Para obtener información sobre el encabezado HTTP Report-Only, consulta Observa problemas con la API de Reporting.

4. Habilita COEP

Este paso solo se puede realizar una vez que te asegures de que los recursos tengan habilitados CORP o CORS.

Una vez que confirmes que todo funciona y que todos los recursos se pueden cargar correctamente, cambia el encabezado Cross-Origin-Embedder-Policy-Report-Only al 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 trabajador.

Determina si el aislamiento se realizó correctamente

La propiedad self.crossOriginIsolated muestra true cuando la página web está 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 encuentres problemas con COOP y COEP. Puedes usar las herramientas para desarrolladores del navegador o la API de Reporting para depurar.

Depura con las Herramientas para desarrolladores de Chrome

Para 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 debe indicar una imagen faltante. Sin embargo, para los recursos que no tienen necesariamente un impacto visual, como las secuencias de comandos o los estilos, los problemas de COEP podrían pasar desapercibidos. Para esos casos, usa el panel de red de Herramientas para desarrolladores.

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

Problemas de COEP en la columna Estado del panel 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 "Marcos" en el lado izquierdo y expande "superior" para ver el desglose de la estructura de recursos.

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

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á aislado de origen cruzado.

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

Observa problemas con la API de Reporting

La API de Reporting es otro mecanismo a través del cual puedes detectar varios problemas. Puedes configurar la API de Reporting para indicarle al navegador de tus usuarios que envíe un informe cada vez que COEP bloquee la carga de un recurso o 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 configurar un servidor para recibir informes.

Informe de COEP de ejemplo

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

[{
  "age": 25101,
  "body": {
    "blocked-url": "https://third-party-test.glitch.me/check.svg?",
    "blockedURL": "https://third-party-test.glitch.me/check.svg?",
    "destination": "image",
    "disposition": "enforce",
    "type": "corp"
  },
  "type": "coep",
  "url": "https://cross-origin-isolation.glitch.me/?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"
}]

Informe de COOP de ejemplo

Una carga útil de informe de COOP de ejemplo 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.glitch.me/popup?report-only&coop=same-origin&",
    "type": "navigation-from-response"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/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 informe"), 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.glitch.me/popup.js",
    "type": "access-from-coop-page-to-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/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.glitch.me/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 habilitar una página web en un estado aislado de origen cruzado especial. 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 pongan a disposición nuevas funciones para este estado aislado de origen cruzado y se realicen más mejoras en Herramientas para desarrolladores en torno a COOP y COEP.

Recursos

Actualizaciones del documento

  • 21 de junio de 2022: Las secuencias de comandos de trabajador 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, debido a un cambio reciente de la dirección, se quitó.
  • 6 de mayo de 2021: Según los comentarios y los problemas informados, decidimos ajustar el cronograma para que el uso de SharedArrayBuffer en sitios no 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 COOP same-origin-allow-popups 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 capacidades, 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 Herramientas para desarrolladores.
  • 15 de octubre de 2020: self.crossOriginIsolated está disponible desde Chrome 87. Como reflejo de eso, document.domain es inmutable cuando self.crossOriginIsolated muestra true. performance.measureUserAgentSpecificMemory() finaliza su prueba de origen y está habilitada de forma predeterminada en Chrome 89. El búfer de array compartido en Android Chrome estará disponible desde Chrome 88.