Cómo hacer que tu sitio web esté "aislado de origen cruzado" con COOP y COEP

Usa COOP y COEP para configurar un entorno aislado de varios orígenes y habilitar funciones potentes, como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() y el temporizador de alta resolución, con mayor precisión.

Actualizaciones

  • 21 de junio de 2022: Las secuencias de comandos de trabajador también deben tener cuidado cuando se habilita el aislamiento entre orígenes. Se agregaron algunas explicaciones.
  • 5 de agosto de 2021: Se mencionó la API de autoperfilación de JS como una de las APIs que requieren aislamiento entre orígenes, pero, debido al cambio reciente de la dirección, se quitó.
  • 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 no aislados de origen cruzado se restrinja en Chrome M92.
  • 16 de abril de 2021: Se agregaron notas sobre un nuevo modo sin credenciales de la COEP y COOP para permitir ventanas emergentes del mismo origen como una condición relajada para el aislamiento entre orígenes.
  • 5 de marzo de 2021: Se quitaron las limitaciones de 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 una 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 DevTools.
  • 15 de octubre de 2020: self.crossOriginIsolated está disponible a partir de Chrome 87. Como resultado, document.domain es inmutable cuando self.crossOriginIsolated muestra true. performance.measureUserAgentSpecificMemory() finalizará su prueba de origen y estará habilitada de forma predeterminada en Chrome 89. El búfer de array compartido en Chrome para Android estará disponible a partir de Chrome 88.

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 habilitación voluntaria llamado aislado de origen cruzado. Con un estado aislado de origen cruzado, la página web podrá usar funciones privilegiadas, como las siguientes:

API Descripción
SharedArrayBuffer Obligatorio para subprocesos de WebAssembly. Esta función está disponible a partir de Chrome 88 para Android. Actualmente, 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 a partir de Chrome 89.
performance.now(), performance.timeOrigin Actualmente, está disponible en muchos navegadores con la resolución limitada a 100 microsegundos o más. Con el aislamiento entre orígenes, 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. (La capacidad de alterar document.domain permite la comunicación entre documentos del mismo sitio y se considera un resquicio 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 le indican al navegador que bloquee la carga de recursos o iframes que no hayan aceptado que los carguen documentos de origen cruzado, y evitan 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 solicitudes de aceptación.

Para determinar si una página web se encuentra en un estado aislado de varios orígenes, puedes examinar self.crossOriginIsolated.

En este artículo, se muestra cómo usar estos encabezados nuevos. En un artículo de seguimiento, proporcionaré más información y contexto.

Implementa COOP y COEP para que tu sitio web esté aislado de varios orígenes

Integra COOP y COEP

1. Establece el encabezado 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 a las ventanas abiertas y se inhabilita la comunicación mutua entre ambas.

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 a través de <iframe>. Si un sitio web (https://a.example) abre una ventana emergente (https://b.example), la ventana del activador y la ventana emergente comparten el mismo contexto de navegación, por lo que tienen acceso entre sí a través de las APIs de DOM, como window.opener.

Grupo de contexto de navegación

Puedes verificar si el abridor de ventanas y el elemento que lo abre están en grupos de contexto de navegación separados desde DevTools.

2. Asegúrate de que los recursos tengan habilitado CORP o CORS

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 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, configura el encabezado Cross-Origin-Resource-Policy: same-origin.
  • Si se espera que el recurso se cargue solo desde el mismo sitio, pero con 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 encabezado Cross-Origin-Resource-Policy: cross-origin si es posible.
  • Para los recursos de origen cruzado 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.
  • En el caso de los iframes, sigue los mismos principios anteriores 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 ni CORS.
  • Para un documento o un trabajador que se entrega con COEP: require-corp, los subrecursos entre dominios 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.

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 prueba con el encabezado Cross-Origin-Embedder-Policy-Report-Only para examinar si la política funciona. Recibirás informes sin bloquear el contenido incorporado.

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

4. Habilita COEP

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 a través de iframes y secuencias de comandos de trabajador.

Determina si el aislamiento se realizó correctamente con self.crossOriginIsolated

La propiedad self.crossOriginIsolated muestra 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 conseguiste aislar correctamente el grupo de contexto de navegación y obtener acceso a funciones potentes, como performance.measureUserAgentSpecificMemory().

Cómo depurar problemas 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 bloqueará y la página indicará que falta una imagen. Sin embargo, en el caso de los recursos que no tienen un impacto visual, como las secuencias de comandos o los estilos, es posible que los problemas de la COEP pasen desapercibidos. Para ellos, usa el panel de red de DevTools. Si hay un problema con el 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 la 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 emergentes a través del panel Application. 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 Chrome DevTools

También puedes verificar el estado de las ventanas emergentes, por ejemplo, si están aisladas de varios orígenes.

Inspector de ventanas emergentes de Chrome DevTools

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 que le indique 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 emergente. Chrome admite la API de Reporting desde la versión 69 para varios usos, incluidos COEP y COOP.

Para aprender a configurar la API de Reporting y un servidor para recibir informes, consulta Cómo usar la API de Reporting.

Ejemplo de informe de COEP

Una carga útil de ejemplo del informe de la COEP cuando se bloquea el 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"
}]

Ejemplo de informe de COOP

Un ejemplo de carga útil del informe COOP cuando se abre una ventana emergente de forma aislada 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"
}]

Conclusión

Usa una combinación de encabezados HTTP de COOP y COEP para que una página web ingrese a un estado aislado especial entre orígenes. Podrás examinar self.crossOriginIsolated para determinar si una página web se encuentra en un estado aislado de origen cruzado.

Mantendré esta publicación actualizada a medida que se implementen nuevas funciones en este estado aislado de origen cruzado y se realicen más mejoras en DevTools en relación con COOP y COEP.

Recursos