Повышение безопасности расширений

Улучшение безопасности в Manifest V3

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

Удалить выполнение произвольных строк

Вы больше не можете выполнять внешнюю логику с помощью executeScript() , eval() и new Function() .

  • Переместите весь внешний код (JS, Wasm, CSS) в пакет расширений.
  • Обновите ссылки на сценарии и стили для загрузки ресурсов из пакета расширения.
  • Используйте chrome.runtime.getURL() для создания URL-адресов ресурсов во время выполнения.
  • Используйте изолированный iframe: eval и new Function(...) по-прежнему поддерживаются в изолированных iframe. Для получения более подробной информации прочтите руководство по изолированным iframes .

Метод executeScript() теперь находится в пространстве имен scripting , а не в пространстве имен tabs . Информацию об обновлении вызовов см. в разделе Move executeScript() .

Есть несколько особых случаев, когда выполнение произвольных строк все еще возможно:

Удаление удаленно размещенного кода

В Манифесте V3 вся логика вашего расширения должна быть частью пакета расширения. Вы больше не можете загружать и выполнять удаленно размещенные файлы в соответствии с политикой Интернет-магазина Chrome . Примеры включают в себя:

  • Файлы JavaScript, полученные с сервера разработчика.
  • Любая библиотека, размещенная на CDN .
  • Связанные сторонние библиотеки, которые динамически извлекают удаленно размещенный код.

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

Функции и логика, управляемые конфигурацией

Ваше расширение загружает и кэширует удаленную конфигурацию (например, файл JSON) во время выполнения. Кэшированная конфигурация определяет, какие функции включены.

Внешняя логика с удаленным сервисом

Ваше расширение вызывает удаленный веб-сервис. Это позволяет вам сохранять конфиденциальность кода и изменять его по мере необходимости, избегая при этом дополнительных затрат на повторную отправку в Интернет-магазин Chrome.

Встраивание удаленно размещенного кода в изолированный iframe

Удаленно размещенный код поддерживается в изолированных фреймах iframe . Обратите внимание, что этот подход не работает, если коду требуется доступ к DOM страницы внедрения.

Объединение сторонних библиотек

Если вы используете популярный фреймворк, такой как React или Bootstrap, который ранее загружали с внешнего сервера, вы можете загрузить минифицированные файлы, добавить их в свой проект и импортировать локально. Например:

<script src="./react-dom.production.min.js"></script>
<link href="./bootstrap.min.css" rel="stylesheet">

Чтобы включить библиотеку в сервис-воркера, установите в манифесте для ключа "background.type" значение "module" и используйте оператор import .

Используйте внешние библиотеки в скриптах, внедряемых с помощью табуляции.

Вы также можете загружать внешние библиотеки во время выполнения, добавляя их в массив files при вызове scripting.executeScript() . Вы по-прежнему можете загружать данные удаленно во время выполнения.

chrome.scripting.executeScript({
  target: {tabId: tab.id},
  files: ['jquery-min.js', 'content-script.js']
});

Внедрить функцию

Если вам нужно больше динамизма, новое свойство func в scripting.executeScript() позволяет вам внедрить функцию в качестве сценария содержимого и передавать переменные с помощью свойства args .

Манифест V2
let name = 'World!';
chrome.tabs.executeScript({
  code: `alert('Hello, ${name}!')`
});

В файле фонового сценария.

Манифест V3
async function getCurrentTab() {/* ... */}
let tab = await getCurrentTab();

function showAlert(givenName) {
  alert(`Hello, ${givenName}`);
}

let name = 'World';
chrome.scripting.executeScript({
  target: {tabId: tab.id},
  func: showAlert,
  args: [name],
});

На заднем плане сервисный работник.

Репозиторий Chrome Extension Samples содержит пример внедрения функции, который вы можете выполнить. Пример getCurrentTab() приведен в ссылке на эту функцию.

Ищите другие обходные пути

Если предыдущие подходы не помогают в вашем случае использования, возможно, вам придется либо найти альтернативное решение (т. е. перейти на другую библиотеку), либо найти другие способы использования функций библиотеки. Например, в случае с Google Analytics вы можете переключиться на протокол измерения Google вместо использования официальной удаленно размещенной версии JavaScript, как описано в нашем руководстве по Google Analytics 4 .

Обновите политику безопасности контента

"content_security_policy" не был удален из файла manifest.json , но теперь это словарь, поддерживающий два свойства: "extension_pages" и "sandbox" .

Манифест V2
{
  ...
  "content_security_policy": "default-src 'self'"
  ...
}
Манифест V3
{
  ...
  "content_security_policy": {
    "extension_pages": "default-src 'self'",
    "sandbox": "..."
  }
  ...
}

extension_pages : относится к контекстам вашего расширения, включая html-файлы и сервис-воркеры.

sandbox : относится к любым изолированным страницам расширений , которые использует ваше расширение.

Удалите неподдерживаемые политики безопасности контента.

Манифест V3 запрещает определенные значения политики безопасности контента в поле "extension_pages" , которые были разрешены в Манифесте V2. В частности, Манифест V3 запрещает те, которые позволяют удаленное выполнение кода. Директивы script-src, object-src и worker-src могут иметь только следующие значения:

  • self
  • none
  • wasm-unsafe-eval
  • Только распакованные расширения: любой источник локального хоста ( http://localhost , http://127.0.0.1 или любой порт в этих доменах).

Значения политики безопасности контента для sandbox не имеют таких новых ограничений.