Борьба с нарушениями кода удаленного хостинга

Удаленно размещенный код, или RHC, — это то, что в Интернет-магазине Chrome называет всем, что выполняется браузером и загружается не из собственных файлов расширения. Такие вещи, как JavaScript и WASM. Он не включает данные или такие вещи, как JSON или CSS.

Почему RHC больше не разрешен?

Расширения Manifest V3 теперь требуют объединения всего кода, который они используют, внутри самого расширения. Раньше вы могли динамически вставлять теги скриптов с любого URL-адреса в Интернете.

Мне сказали, что на моем добавочном номере есть RHC. Что происходит?

Если ваше расширение было отклонено во время проверки из-за ошибки Blue Argon , наши рецензенты полагают, что ваше расширение использует удаленно размещенный код. Обычно это является результатом того, что расширение пытается добавить тег сценария к удаленному ресурсу (т. е. из открытого Интернета, а не из файлов, включенных в расширение) или получает ресурс для непосредственного выполнения.

Как обнаружить RHC

Обнаружить RHC не так уж и сложно, если знать, что искать. Сначала проверьте наличие в проекте строк «http://» или «https://». Если у вас есть нарушение RHC, вы, скорее всего, сможете их обнаружить, обнаружив это. Если у вас есть полная система сборки или вы используете зависимости из npm или других сторонних источников, убедитесь, что вы ищете скомпилированную версию кода, поскольку именно она оценивается хранилищем. Если вам по-прежнему не удается найти проблему, следующим шагом будет обращение в службу поддержки One Stop . Они смогут обозначить конкретные нарушения и указать, что необходимо для скорейшей публикации расширения.

Что делать, если библиотека запрашивает код

Независимо от того, откуда взят код, в нем не допускается наличие RHC. Сюда входит код, который вы не писали, но случайно использовали в качестве зависимости в своем проекте. У некоторых разработчиков , использующих Firebase, возникла эта проблема, когда удаленный код включался для использования в Firebase Auth . Несмотря на то, что это была собственная библиотека (т. е. принадлежащая Google), для RHC не предусмотрено никаких исключений. Вам необходимо настроить код, чтобы либо удалить RHC, либо обновить проект, чтобы он не включал код с самого начала. Если вы столкнулись с проблемой, когда RHC загружается не вашим кодом, а библиотекой, которую вы используете, то лучше всего обратиться к автору библиотеки. Сообщите им, что это происходит, и попросите либо обходной путь, либо обновления кода для ее устранения.

Что делать, если вы не можете дождаться обновления библиотеки

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

Аудит кода

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

Альтернативно, есть ли другая библиотека, предлагающая те же функции? Попробуйте проверить npmjs.com , GitHub или другие сайты на наличие других вариантов, соответствующих тем же сценариям использования.

Дерево трясется

Если код, вызывающий нарушение RHC, на самом деле не используется, его можно автоматически удалить с помощью инструмента. Современные инструменты сборки, такие как webpack , Rollup и Vite (и это лишь некоторые из них), имеют функцию, называемую Tree-Shaking . После включения в вашей системе сборки встряхивание дерева должно удалить все неиспользуемые пути кода. Это может означать, что у вас есть не только более совместимая версия вашего кода, но и более компактная и быстрая! Важно отметить, что не все библиотеки могут быть встряхнуты, но многие из них способны. В некоторых инструментах, таких как Rollup и Vite, по умолчанию включено встряхивание дерева. Для его включения необходимо настроить веб-пакет. Если вы не используете систему сборки как часть своего расширения, но используете библиотеки кода, вам действительно рекомендуется изучить возможность добавления инструмента сборки в ваш рабочий процесс. Инструменты сборки помогают писать более безопасные, надежные и удобные в сопровождении проекты.

Особенности реализации Treeshaking зависят от вашего конкретного проекта. Но если взять простой пример с Rollup, вы можете добавить Treeshaking, просто скомпилировав код проекта. Например, если у вас есть файл main.js, который предназначен только для входа в Firebase Auth:

import { GoogleAuthProvider, initializeAuth } from "firebase/auth";

chrome.identity.getAuthToken({ 'interactive': true }, async (token) => {
  const credential = GoogleAuthProvider.credential(null, token);
  try {
    const app = initializeApp({ ... });
    const auth = initializeAuth(app, { popupRedirectResolver: undefined, persistence: indexDBLocalPersistence });
    const { user } = await auth.signInWithCredential(credential)
    console.log(user)
  } catch (e) {
    console.error(error);
  }
});

Затем все, что вам нужно сделать, это указать Rollup входной файл, плагин, необходимый для загрузки файлов узлов @rollup/plugin-node-resolve , и имя выходного файла, который он генерирует.

npx rollup --input main.js --plugin '@rollup/plugin-node-resolve' --file compiled.js

Запустив эту команду в окне терминала, вы получите сгенерированную версию нашего файла main.js , скомпилированную в один файл с именем compiled.js .

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

Автоматическое редактирование файлов

Все более распространенным способом проникновения удаленно размещенного кода в вашу кодовую базу является использование подзависимой библиотеки, которую вы включаете. Если библиотека X хочет import библиотеку Y из CDN, вам все равно придется обновить ее, чтобы она загружалась из локального источника. С помощью современных систем сборки вы можете легко создавать плагины для извлечения удаленной ссылки и встраивать ее непосредственно в свой код.

Это будет означать, что данный код выглядит следующим образом:

import moment from "https://unpkg.com/moment@2.29.4/moment.js"
console.log(moment())

Вы можете сделать небольшой плагин для объединения.

import { existsSync } from 'fs';
import fetch from 'node-fetch';

export default {
  plugins: [{
    load: async function transform(id, options, outputOptions) {
      // this code runs over all of out javascript, so we check every import
      // to see if it resolves as a local file, if that fails, we grab it from
      // the network using fetch, and return the contents of that file directly inline
      if (!existsSync(id)) {
        const response = await fetch(id);
        const code = await response.text();

        return code
      }
      return null
    }
  }]
};

Как только вы запустите сборку с новым плагином, каждый URL-адрес удаленного import будет обнаружен независимо от того, был ли это наш код, субзависимость, субзависимость или где-то еще.

npx rollup --input main.js --config ./rollup.config.mjs --file compiled.js

Редактирование файлов вручную

Самый простой вариант — просто удалить код, вызывающий RHC. Откройте любой текстовый редактор и удалите нарушающие строки. Обычно это не рекомендуется, потому что это хрупко и о нем можно забыть. Это усложняет поддержку вашего проекта, если файл с именем «library.min.js» на самом деле не является библиотекой.min.js. Вместо редактирования необработанных файлов немного более удобный вариант — использовать такой инструмент, как patch-package . Это очень мощная опция, которая позволяет сохранять изменения в файле, а не в самом файле. Он построен на файлах исправлений , таких же, как в системах контроля версий, таких как Git или Subversion . Вам просто нужно вручную изменить нарушающий код, сохранить файл различий и настроить пакет исправлений с изменениями, которые вы хотите применить. Полное руководство можно прочитать в readme проекта . Если вы исправляете проект, мы настоятельно рекомендуем вам обратиться к проекту и попросить внести изменения в исходную версию. Хотя пакет patch-package значительно упрощает управление исправлениями, еще лучше, когда нечего исправлять.

Что делать, если код не используется

По мере роста кодовых баз зависимости (или зависимость зависимости, или зависимость…) могут сохранять пути кода, которые больше не используются. Если один из этих разделов содержит код для загрузки или выполнения RHC, его придется удалить. Неважно, мертв он или не используется. Если он не используется, его следует удалить либо путем встряхивания дерева, либо путем исправления библиотеки для его удаления.

Есть ли обходной путь?

Вообще говоря, нет. РВК не допускается. Однако есть небольшое количество случаев, когда это разрешено. Это почти всегда случаи, когда никакой другой вариант невозможен.

API пользовательских сценариев

Пользовательские сценарии — это небольшие фрагменты кода, которые обычно предоставляются пользователем и предназначены для менеджеров пользовательских сценариев, таких как TamperMonkey и Violentmonkey . Эти менеджеры не могут объединять код, написанный пользователями, поэтому API пользовательских сценариев предоставляет способ выполнения кода, предоставленного пользователем. Это не замена chrome.scripting.executeScript или других сред выполнения кода. Пользователи должны включить режим разработчика , чтобы выполнить что-либо. Если группа проверки Интернет-магазина Chrome посчитает, что он используется не по назначению (т. е. код, предоставленный пользователем), он может быть отклонен или его список будет удален из магазина.

chrome.debugger

API chrome.debugger дает расширениям возможность взаимодействовать с протоколом Chrome Devtools . Это тот же протокол, который используется для Devtools Chrome и огромного количества других инструментов . С его помощью расширение может запрашивать и выполнять удаленный код. Как и пользовательские скрипты, он не заменяет chrome.scripting и обеспечивает гораздо более удобный пользовательский опыт. Во время использования пользователь будет видеть панель предупреждения в верхней части окна. Если баннер закрыт или отклонен, сеанс отладки будет завершен.

Снимок экрана адресной строки Chrome с сообщением «Расширение отладчика начало отладку этого браузера».
Снимок экрана адресной строки Chrome с сообщением «Расширение отладчика начало отладку этого браузера».

Изолированные iframe в песочнице

Если вам нужно оценить строку как код и вы находитесь в среде DOM (например, в сценарии контента, а не в рабочем сервисе расширений), то другой вариант — использовать изолированный iframe . Расширения по умолчанию не поддерживают такие функции, как eval() в целях безопасности. Вредоносный код может поставить под угрозу безопасность и безопасность пользователей. Но когда код выполняется только в заведомо безопасной среде, например в iframe, изолированном от остальной части Интернета, эти риски значительно снижаются. В этом контексте политика безопасности контента, которая блокирует использование eval, может быть отменена, что позволит вам запускать любой действительный код JavaScript.

Если у вас есть вариант использования, который не описан, не стесняйтесь обратиться к команде, используя список рассылки chromium-extensions, чтобы получить отзыв, или откройте новый запрос, чтобы запросить рекомендации от One Stop Support.

Что делать, если вы не согласны с приговором

Обеспечение соблюдения политик может иметь нюансы, а проверка требует ручного ввода, а это означает, что команда Интернет-магазина Chrome иногда может согласиться изменить решение о проверке. Если вы считаете, что при проверке была допущена ошибка, вы можете обжаловать отказ с помощью службы One Stop Support.