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 origen cruzado y habilitar funciones potentes, como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() y un temporizador de alta resolución con mayor precisión.

Actualizaciones

  • 21 de junio de 2022: Las secuencias de comandos de trabajadores también necesitan cuidado cuando está habilitado el aislamiento de origen cruzado. Se agregaron algunas explicaciones.
  • 5 de agosto de 2021: Se mencionó a la API de JS Self-Profiling como una de las APIs que requieren aislamiento de origen cruzado, pero se quitó, debido a un cambio reciente en la dirección.
  • 6 de mayo de 2021: A partir de los comentarios y los problemas informados, decidimos ajustar el cronograma del uso de SharedArrayBuffer en ningún sitio aislado de origen cruzado en Chrome M92.
  • 16 de abril de 2021: Se agregaron notas sobre un nuevo modo sin credenciales de COEP y las ventanas emergentes de permiso del mismo origen COOP como una condición relajada para el aislamiento de origen cruzado.
  • 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 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 Herramientas para desarrolladores.
  • 15 de octubre de 2020: self.crossOriginIsolated está disponible a partir de Chrome 87. A modo de referencia, document.domain es inmutable cuando self.crossOriginIsolated muestra true. performance.measureUserAgentSpecificMemory() finalizará su prueba de origen y está habilitado 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 que se denomina aislado de origen cruzado. Con un estado aislado de origen cruzado, la página web podrá usar funciones con privilegios, incluidas las siguientes:

API Descripción
SharedArrayBuffer Obligatorio para los subprocesos de WebAssembly. Esta función está disponible desde Android Chrome 88. 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 de origen cruzado, la resolución puede ser de 5 microsegundos o más.
Funciones que estarán disponibles con un estado aislado de origen cruzado.

El estado aislado de origen cruzado también evita modificaciones de document.domain. (Poder modificar document.domain permite la comunicación entre documentos del mismo sitio y se considera una oportunidad 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 habilitado la carga 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 en orígenes cruzados requieren habilitación.

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

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

Implementa las funciones COOP y COEP para aislar el origen cruzado de tu sitio web

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 COOP. Por lo tanto, el aislamiento se aplica de manera forzosa para las ventanas abiertas y la comunicación mutua entre ambas ventanas está inhabilitada.

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 mediante <iframe>. Si un sitio web (https://a.example) abre una ventana emergente (https://b.example), la ventana de apertura 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 activador de ventanas y el elemento abierto están en grupos de contexto de navegación separados desde Herramientas para desarrolladores.

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

Asegúrate de que todos los recursos de la página estén cargados con encabezados HTTP de CORP o CORS. Este paso es obligatorio en el paso cuatro, habilitar 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 de origen cruzado, configura el encabezado Cross-Origin-Resource-Policy: same-site.
  • Si el recurso se carga desde orígenes cruzados bajo tu control, configura el encabezado Cross-Origin-Resource-Policy: cross-origin si es posible.
  • Para recursos de origen cruzado que no controlas:
    • 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 que se mencionaron anteriormente 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.
  • En el caso de un documento o un trabajador entregado con COEP: require-corp, los subrecursos de origen cruzado que se cargan sin CORS deben configurar 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 informe COEP para evaluar los recursos incorporados

Antes de habilitar el COEP por completo, 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 trabajador. Para obtener información sobre el encabezado HTTP de solo informe, consulta Cómo observar problemas con la API de Reporting.

4. Habilitar 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 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 potentes como performance.measureUserAgentSpecificMemory().

Depura 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 porque se bloqueará la solicitud y la página indicará que falta una imagen. Sin embargo, en el caso de los recursos que no necesariamente tienen un impacto visual, como secuencias de comandos o estilos, los problemas de COEP pueden pasar desapercibidos. Para ellos, usa el panel Network de Herramientas para desarrolladores. 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 error de COEP se muestran en la pestaña Encabezados después de hacer clic en un recurso de red en el panel Network.

También puedes determinar el estado de los iframes y las ventanas emergentes mediante el panel Application. Ve a la sección "Frames" (Fotogramas) en el lado izquierdo y expande la sección "top" (parte 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 emergentes, por ejemplo, si están aislados de orígenes cruzados.

Inspector de ventanas emergentes de las Herramientas para desarrolladores de Chrome

Observa problemas con la API de Reporting

La API de Reporting es otro mecanismo mediante el cual puedes detectar varios problemas. Puedes configurar la API de Reporting para que el navegador de tus usuarios envíe un informe cada vez que COEP bloquee la carga de un recurso o COOP aísle una ventana emergente. Chrome es compatible con la API de Reporting desde la versión 69 para una variedad de usos, incluidos COEP y COOP.

Si deseas aprender a configurar la API de Reporting y configurar un servidor para que reciba informes, ve a Cómo usar la API de Reporting.

Ejemplo de informe COEP

Una carga útil de ejemplo de un informe de COEP cuando el recurso de origen cruzado está bloqueado 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 COOP

Una carga útil de ejemplo de un informe COOP cuando se abre una ventana emergente 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 contextos de navegación intentan acceder unos a otros (solo en el modo de "solo informes"), COOP también envía un informe. Por ejemplo, un informe cuando se intenta realizar la acción postMessage() tendría el siguiente aspecto:

[{
  "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 COOP y COEP para habilitar un estado especial aislado de origen cruzado en una página web. Podrás examinar self.crossOriginIsolated para determinar si una página web se encuentra en estado aislado de origen cruzado.

Mantendremos esta publicación actualizada a medida que haya nuevas funciones disponibles para este estado aislado de origen cruzado y se realicen mejoras adicionales en Herramientas para desarrolladores en relación con COOP y COEP.

Recursos