Как сделать сайт с изоляцией от междоменных источников с помощью COOP и COEP

Используйте COOP и COEP, чтобы настроить среду с изоляцией от междоменных источников и включить такие мощные функции, как SharedArrayBuffer, performance.measureUserAgentSpecificMemory() и таймер высокого разрешения с повышенной точностью.

Дата публикации: 13 апреля 2020 г. Последнее обновление: 21 июня 2022 г.

В этом документе рассказывается, как использовать COOP и COEP. Подробнее о том, почему это важно, читайте в статье Как сделать сайт «с изоляцией от междоменных источников» с помощью COOP и COEP.

Некоторые веб-API повышают риск атак по сторонним каналам, таких как Spectre. Чтобы снизить этот риск, браузеры предлагают изолированную среду на основе согласия, которая называется изоляцией от междоменных источников. В состоянии с изоляцией от междоменных источников веб-страница сможет использовать привилегированные функции, в том числе:

API Описание
SharedArrayBuffer Требуется для потоков WebAssembly. Эта функция доступна в Chrome 88 для Android. В версии для ПК он по умолчанию включен с помощью изоляции сайтов, но для него потребуется состояние с изоляцией от междоменных источников, и в Chrome 92 он будет по умолчанию отключен.
performance.measureUserAgentSpecificMemory() Доступно в Chrome 89 и более поздних версиях.
performance.now(), performance.timeOrigin Доступно во многих браузерах, разрешение ограничено 100 микросекундами или более. При изоляции от междоменных источников разрешение может быть 5 микросекунд или выше.
Функции, которые будут доступны в состоянии с изоляцией от междоменных источников.

Состояние с изоляцией от междоменных источников также предотвращает изменение document.domain. Возможность изменять document.domain позволяет документам на одном сайте обмениваться данными, что считается лазейкой в политике одинакового источника.

Чтобы включить изоляцию от междоменных источников, необходимо отправить следующие HTTP-заголовки в основном документе:

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

Эти заголовки указывают браузеру, что нужно блокировать загрузку ресурсов или фреймов iframe, которые не разрешили загрузку в документах из разных источников, и запрещают окнам из разных источников напрямую взаимодействовать с вашим документом. Это также означает, что для ресурсов, загружаемых из разных источников, требуется согласие.

Чтобы узнать, находится ли веб-страница в состоянии с изоляцией от междоменных источников, проверьте свойство self.crossOriginIsolated.

Глоссарий

В этом документе используется много похожих терминов и сокращений. Чтобы вам было проще разобраться, мы составили небольшой глоссарий:

Как настроить изоляцию от междоменных источников на сайте

1. Задайте Cross-Origin-Opener-Policy: same-origin в документе верхнего уровня

Если включить COOP: same-origin в документе верхнего уровня, то окна с тем же источником и окна, открытые из документа, будут иметь отдельную группу контекста браузера, если только они не находятся в одном источнике с той же настройкой COOP. Таким образом, для открытых окон применяется изоляция, а взаимная связь между ними отключается.

Группа контекста просмотра – это набор окон, которые могут ссылаться друг на друга. Например, документ верхнего уровня и его дочерние документы, встроенные с помощью <iframe>. Если сайт (https://a.example) открывает диалоговое окно (https://b.example), у них будет общий контекст просмотра, поэтому они смогут получить доступ друг к другу с помощью API DOM, например window.opener.

Иллюстрация, представляющая группу контента &quot;Просмотр&quot;, на которой пользователь взаимодействует с элементами страницы.

Проверить, находятся ли окно и открытая в нем страница в разных группах контекста браузера, можно в Инструментах разработчика.

2. Как включить CORP или CORS для ресурсов

Убедитесь, что все ресурсы на странице загружаются с HTTP-заголовками CORP или CORS. Это необходимо для шага 4 – включения COEP.

Вот что нужно сделать в зависимости от типа ресурса:

  • Если ресурс должен загружаться только из того же источника, задайте заголовок Cross-Origin-Resource-Policy: same-origin.
  • Если ресурс должен загружаться только с того же сайта, но из разных источников, задайте заголовок Cross-Origin-Resource-Policy: same-site.
  • Если ресурс загружается из нескольких источников, которые вы контролируете, по возможности задайте заголовок Cross-Origin-Resource-Policy: cross-origin.
  • Если вы не можете управлять ресурсами из разных источников:
    • Если ресурс передается с помощью CORS, используйте атрибут crossorigin в теге загрузки HTML. Пример: <img src="***" crossorigin>.
    • Попросите владельца ресурса добавить поддержку CORS или CORP.
  • Для элементов iframe действуют те же принципы. Задайте атрибут Cross-Origin-Resource-Policy: cross-origin (или same-site, same-origin в зависимости от контекста).
  • Скрипты, загруженные с помощью WebWorker, должны обслуживаться из одного источника, поэтому вам не нужны заголовки CORP или CORS.
  • Для документа или обработчика, обслуживаемого с помощью COEP: require-corp, в подресурсах из разных источников, загружаемых без CORS, должен быть задан заголовок Cross-Origin-Resource-Policy: cross-origin, чтобы разрешить встраивание. Например, это относится к <script>, importScripts, <link>, <video>, <iframe> и т. д.

Изоляция в окнах iframe

Вы можете включить изоляцию от междоменных источников для документа, встроенного в iframe, применив правило разрешений allow="cross-origin-isolated" к тегу <iframe> и выполнив указанные ниже условия. Вся цепочка документов, включая родительские и дочерние фреймы, также должна быть изолирована от междоменных источников.

3. Как использовать HTTP-заголовок COEP Report-Only для оценки встроенных ресурсов

Прежде чем полностью включить COEP, вы можете выполнить пробный запуск, используя заголовок Cross-Origin-Embedder-Policy-Report-Only, чтобы проверить, действительно ли работает политика. Вы будете получать отчеты, но встроенный контент не будет блокироваться.

Рекурсивно примените это ко всем документам, включая документ верхнего уровня, окна iframe и скрипты worker. Дополнительную информацию о заголовке HTTP Report-Only можно найти в статье Как отслеживать проблемы с помощью Reporting API.

4. Как включить COEP

Этот шаг можно выполнить только после того, как вы убедитесь, что для ресурсов включены заголовки CORP или CORS.

Убедившись, что все работает и ресурсы загружаются, замените заголовок Cross-Origin-Embedder-Policy-Report-Only на заголовок Cross-Origin-Embedder-Policy с тем же значением для всех документов, включая встроенные с помощью iframe и скриптов worker.

Как определить, что изоляция выполнена успешно

Свойство self.crossOriginIsolated возвращает значение true, когда веб-страница находится в состоянии изоляции от междоменных источников, а все ресурсы и окна изолированы в рамках одной группы контекста просмотра. С помощью этого API можно определить, удалось ли вам изолировать группу контекста просмотра и получить доступ к таким функциям, как performance.measureUserAgentSpecificMemory().

Устранить проблемы.

Вы можете столкнуться с проблемами, связанными с COOP и COEP. Для отладки можно использовать инструменты разработчика в браузере или Reporting API.

Отладка с помощью инструментов разработчика Chrome

Для ресурсов, которые отображаются на экране, например изображений, обнаружить проблемы с COEP довольно просто, поскольку запрос блокируется и на странице должно быть указано отсутствующее изображение. Однако для ресурсов, которые не обязательно имеют визуальное воздействие, таких как скрипты или стили, проблемы с COEP могут остаться незамеченными. Для этого используйте панель "Сеть" в Инструментах разработчика.

Если с COEP возникла проблема, в столбце Status (Статус) появится значение (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep).

Проблемы с COEP в столбце &quot;Статус&quot; на панели &quot;Сеть&quot;.

Нажмите на запись, чтобы посмотреть подробные сведения.

Подробные сведения о проблеме с COEP показаны на вкладке &quot;Заголовки&quot; после нажатия на сетевой ресурс на панели &quot;Сеть&quot;.

Вы также можете определить статус окон iframe и диалоговых окон на панели Приложение. Перейдите в раздел Frames (Фреймы) на панели слева и разверните раздел top (верх), чтобы увидеть структуру ресурсов.

Вы можете проверить статус iframe, например доступность SharedArrayBuffer.

Инспектор iframe в инструментах разработчика Chrome.

Вы также можете проверить статус диалогового окна, например изолировано ли оно от междоменных источников.

Инспектор диалоговых окон в инструментах разработчика Chrome

Как отслеживать проблемы с помощью Reporting API

Reporting API – это ещё один механизм, с помощью которого можно выявлять различные проблемы. Вы можете настроить Reporting API так, чтобы браузеры пользователей отправляли отчет каждый раз, когда COEP блокирует загрузку ресурса или COOP изолирует диалоговое окно. Reporting API поддерживается в Chrome начиная с версии 69 и используется для разных целей, в том числе для COEP и COOP.

Узнайте, как настроить Reporting API и сервер для получения отчетов.

Пример отчета COEP

Пример полезной нагрузки отчета COEP, когда перекрестный ресурс заблокирован:

[{
  "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"
}]

Пример отчета COOP

Пример полезной нагрузки отчета COOP, когда диалоговое окно открывается изолированно:

[{
  "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"
}]

Когда разные группы контекста просмотра пытаются получить доступ друг к другу (только в режиме report-only), COOP также отправляет отчет. Например, отчет о попытке выполнить команду postMessage() будет выглядеть так:

[{
  "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"
}]

Выводы

Чтобы перевести веб-страницу в специальное состояние с изоляцией от междоменных источников, используйте комбинацию HTTP-заголовков COOP и COEP. Чтобы определить, изолирована ли веб-страница от междоменных источников, проверьте self.crossOriginIsolated.

Мы будем обновлять эту запись по мере того, как в состоянии с изоляцией от междоменных источников будут появляться новые функции, а в Инструментах разработчика – улучшения, связанные с COOP и COEP.

Ресурсы

Обновления документов

  • 21 июня 2022 г. При включении изоляции от междоменных источников необходимо также уделить внимание скриптам рабочих процессов. Добавлены пояснения.
  • 5 августа 2021 г. JS Self-Profiling API был упомянут как один из API, требующих изоляции от междоменных источников, но в связи с недавним изменением направления он был удален.
  • 6 мая 2021 г. На основе отзывов и сообщений о проблемах мы решили скорректировать график ограничения использования SharedArrayBuffer на сайтах без изоляции от междоменных источников в Chrome M92.
  • 16 апреля 2021 г. Добавлены примечания о режиме COEP без учетных данных и значении same-origin-allow-popups заголовка COOP как менее строгом условии для изоляции от междоменных источников.
  • 5 марта 2021 г. Сняты ограничения для функций SharedArrayBuffer, performance.measureUserAgentSpecificMemory() и отладки. Теперь они полностью доступны в Chrome 89. Добавлены новые возможности, performance.now() и performance.timeOrigin, которые будут иметь более высокую точность.
  • 19 февраля 2021 г. Добавлено примечание о правилах в отношении функцийallow="cross-origin-isolated" и отладке в Инструментах разработчика.
  • 15 октября 2020 г. self.crossOriginIsolated доступен в Chrome 87. Поэтому document.domain является неизменяемым, когда self.crossOriginIsolated возвращает true. Эксперимент с источником для performance.measureUserAgentSpecificMemory() завершается, и в Chrome 89 эта функция будет включена по умолчанию. Shared Array Buffer в Chrome для Android будет доступен начиная с версии 88.