Postępowanie w przypadku naruszeń kodu hostowanych zdalnie

Kod hostowany zdalnie, czyli RHC, to w Chrome Web Store wszystko, co jest wykonywane przez przeglądarkę i wczytywane z innego miejsca niż pliki rozszerzenia. takich jak JavaScript i WASM. Nie obejmuje danych ani elementów takich jak JSON czy CSS.

Dlaczego RHC jest już niedozwolone?

W przypadku rozszerzeń korzystających z platformy Manifest V3 cały używany kod musi być dołączony do samego rozszerzenia. W przeszłości można było dynamicznie wstawiać tagi skryptu z dowolnego adresu URL w internecie.

Powiedziano mi, że moje rozszerzenie ma RHC. Co się dzieje?

Jeśli Twoje rozszerzenie zostało odrzucone podczas sprawdzania z powodu błędu Blue Argon, oznacza to, że nasi weryfikatorzy uważają, że korzysta ono z kodu hostowanego zdalnie. Zwykle jest to spowodowane tym, że rozszerzenie próbuje dodać tag skryptu ze zdalnym zasobem (tzn. z otwartej sieci, a nie z plików zawartych w rozszerzeniu) lub pobrać zasób do bezpośredniego wykonania.

Jak rozpoznać RHC

Wykrycie RHC nie jest szczególnie trudne, jeśli wiesz, na co zwrócić uwagę. Najpierw sprawdź, czy w projekcie występują ciągi znaków „http://” lub „https://”. Jeśli masz naruszenie zasad dotyczących reklam o charakterze politycznym, prawdopodobnie znajdziesz je w ten sposób. Jeśli masz pełny system kompilacji lub używasz zależności z npm lub innych źródeł zewnętrznych, upewnij się, że przeszukujesz skompilowaną wersję kodu, ponieważ to ona jest oceniana przez sklep. Jeśli nadal nie możesz znaleźć przyczyny problemu, skontaktuj się z zespołem pomocy. Będą mogli wskazać konkretne naruszenia i wyjaśnić, co należy zrobić, aby jak najszybciej opublikować rozszerzenie.

Co zrobić, jeśli biblioteka prosi o kod

Niezależnie od tego, skąd pochodzi kod, nie może on zawierać RHC. Dotyczy to kodu, którego nie jesteś autorem, ale który jest używany jako zależność w Twoim projekcie. Niektórzy deweloperzy korzystający z Firebase mieli ten problem, gdy do użycia w Firebase Auth dołączano zdalny kod. Mimo że była to biblioteka własna (czyli należąca do Google), nie ma wyjątku w przypadku RHC. Musisz skonfigurować kod tak, aby usuwał RHC, lub zaktualizować projekt, aby nie zawierał tego kodu. Jeśli problem polega na tym, że RHC nie jest wczytywany przez Twój kod, ale przez używaną przez Ciebie bibliotekę, najlepszym rozwiązaniem jest skontaktowanie się z autorem biblioteki. Poinformuj ich o tym i poproś o rozwiązanie lub aktualizację kodu, aby usunąć ten problem.

Co zrobić, jeśli nie możesz czekać na aktualizację biblioteki

Niektóre biblioteki udostępnią aktualizację niemal natychmiast po otrzymaniu powiadomienia, ale inne mogą zostać porzucone lub potrzebować czasu na rozwiązanie problemu. W zależności od tego, co się dzieje w przypadku konkretnego naruszenia, możesz nie musieć czekać, aż użytkownik podejmie działania, aby odblokować konto i pomyślnie przejść weryfikację. Dostępnych jest kilka opcji, które pozwolą Ci szybko wrócić do pracy.

Sprawdź kod

Czy na pewno potrzebujesz kodu, który powoduje wysłanie prośby? Jeśli można go po prostu usunąć lub usunąć bibliotekę, która go powoduje, usuń ten kod i gotowe.

Czy istnieje inna biblioteka, która oferuje te same funkcje? Sprawdź npmjs.com, GitHub lub inne witryny, aby znaleźć inne opcje, które spełniają te same przypadki użycia.

Potrząsanie drzewem

Jeśli kod powodujący naruszenie zasad RHC nie jest używany, narzędzia mogą go automatycznie usunąć. Nowoczesne narzędzia do kompilacji, takie jak webpack, RollupVite (to tylko kilka przykładów), mają funkcję o nazwie tree-shaking. Po włączeniu w systemie kompilacji funkcja tree shaking powinna usunąć wszystkie nieużywane ścieżki kodu. Może to oznaczać, że masz nie tylko bardziej zgodną z przepisami wersję kodu, ale też bardziej przejrzystą i szybszą. Warto pamiętać, że nie wszystkie biblioteki można poddać tree shakingowi, ale wiele z nich tak. Niektóre narzędzia, takie jak Rollup i Vite, mają domyślnie włączone usuwanie nieużywanego kodu. W przypadku webpacka trzeba skonfigurować tę funkcję. Jeśli nie używasz systemu kompilacji w ramach rozszerzenia, ale korzystasz z bibliotek kodu, zdecydowanie zalecamy dodanie narzędzia do kompilacji do swojego procesu. Narzędzia do kompilacji pomagają pisać bezpieczniejsze, bardziej niezawodne i łatwiejsze w utrzymaniu projekty.

Szczegóły implementacji usuwania nieużywanego kodu zależą od konkretnego projektu. Weźmy prosty przykład z Rollup: aby dodać eliminację martwego kodu, wystarczy skompilować kod projektu. Jeśli na przykład masz plik, który loguje się tylko w usłudze Firebase Authentication, o nazwie main.js:

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);
  }
});

Wystarczy, że podasz Rollupowi plik wejściowy, wtyczkę potrzebną do wczytywania plików węzła @rollup/plugin-node-resolve i nazwę generowanego pliku wyjściowego.

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

Po uruchomieniu tego polecenia w oknie terminala otrzymasz wygenerowaną wersję pliku main.js, skompilowaną w jednym pliku o nazwie compiled.js.

Podsumowanie może być proste, ale jest też bardzo konfigurowalne. Możesz dodawać wszelkiego rodzaju złożoną logikę i konfigurację. Wystarczy, że zapoznasz się z dokumentacją. Dodanie narzędzi do kompilacji, takich jak to, spowoduje, że kod będzie mniejszy i wydajniejszy, a w tym przypadku rozwiąże problem z kodem hostowanym zdalnie.

Automatyczna edycja plików

Coraz częściej zdarza się, że kod hostowany zdalnie trafia do bazy kodu jako podzależność biblioteki, którą uwzględniasz. Jeśli biblioteka X chce pobraćimport bibliotekę Y z sieci CDN, musisz ją zaktualizować, aby wczytywała się z lokalnego źródła. W przypadku nowoczesnych systemów kompilacji możesz łatwo tworzyć wtyczki do wyodrębniania odwołania zdalnego i wstawiania go bezpośrednio do kodu.

Oznacza to, że w przypadku kodu, który wygląda tak:

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

Możesz utworzyć małą wtyczkę do Rollup.

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
    }
  }]
};

Po uruchomieniu kompilacji z nową wtyczką każdy zdalny adres URL import zostanie wykryty niezależnie od tego, czy był to nasz kod, podzależność, podpodzależność czy jakikolwiek inny element.

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

Ręczne edytowanie plików

Najprostszym rozwiązaniem jest usunięcie kodu, który powoduje RHC. Otwórz go w wybranym edytorze tekstu i usuń wiersze naruszające zasady. Zwykle nie jest to zalecane, ponieważ jest to rozwiązanie nietrwałe i można o nim zapomnieć. Utrudnia to utrzymanie projektu, gdy plik o nazwie „library.min.js” nie jest w rzeczywistości plikiem library.min.js. Zamiast edytować surowe pliki, możesz użyć narzędzia takiego jak patch-package. Jest to nieco łatwiejsze w utrzymaniu rozwiązanie. Jest to bardzo przydatna opcja, która umożliwia zapisywanie modyfikacji w pliku, a nie samego pliku. Jest on oparty na plikach poprawek, czyli na tym samym, co systemy kontroli wersji, takie jak Git czy Subversion. Wystarczy ręcznie zmodyfikować kod naruszający zasady, zapisać plik różnicowy i skonfigurować patch-package ze zmianami, które chcesz zastosować. Pełny samouczek znajdziesz w pliku README projektu. Jeśli poprawiasz projekt, zdecydowanie zachęcamy do skontaktowania się z nim i poproszenia o wprowadzenie zmian w źródle. Chociaż patch-package znacznie ułatwia zarządzanie poprawkami, jeszcze lepiej jest, gdy nie ma nic do poprawiania.

Co zrobić, jeśli kod nie jest używany

Wraz z rozwojem baz kodu zależności (lub zależności zależności, lub zależności zależności…) mogą utrzymywać ścieżki kodu, które nie są już używane. Jeśli w jednej z tych sekcji znajduje się kod do wczytywania lub wykonywania RHC, należy go usunąć. Nie ma znaczenia, czy jest martwy czy nieużywany. Jeśli nie jest używana, należy ją usunąć, stosując tree shaking lub poprawiając bibliotekę.

Czy istnieje jakieś obejście tego problemu?

Zasadniczo nie. RHC jest niedozwolone. Istnieje jednak niewielka liczba przypadków, w których jest to dozwolone. Są to prawie zawsze przypadki, w których żadna inna opcja nie jest możliwa.

User Scripts API

Skrypty użytkownika to małe fragmenty kodu, które są zwykle dostarczane przez użytkownika i przeznaczone dla menedżerów skryptów użytkownika, takich jak TamperMonkeyViolentmonkey. Nie mogą one łączyć kodu napisanego przez użytkowników, dlatego interfejs User Script API udostępnia sposób wykonywania kodu dostarczonego przez użytkownika. Nie jest to zamiennik chrome.scripting.executeScript ani innych środowisk wykonywania kodu. Aby cokolwiek wykonać, użytkownicy muszą włączyć tryb deweloperski. Jeśli zespół weryfikujący Chrome Web Store uzna, że jest on używany w sposób niezgodny z przeznaczeniem (np. kod dostarczony przez użytkownika), może odrzucić rozszerzenie lub usunąć je ze sklepu.

chrome.debugger

Interfejs chrome.debugger API umożliwia rozszerzeniom interakcję z protokołem Narzędzi deweloperskich w Chrome. Jest to ten sam protokół, który jest używany w narzędziach deweloperskich Chrome i wielu innych narzędziach. Dzięki temu rozszerzenie może wysyłać żądania dotyczące kodu zdalnego i go wykonywać. Podobnie jak skrypty użytkownika nie zastępuje ona interfejsu chrome.scripting i zapewnia znacznie lepsze wrażenia użytkownika. Podczas korzystania z tej funkcji użytkownik zobaczy pasek ostrzegawczy u góry okna. Jeśli baner zostanie zamknięty lub odrzucony, sesja debugowania zostanie zakończona.

Zrzut ekranu przedstawiający pasek adresu w Chrome z komunikatem „Rozszerzenie debugera rozpoczęło debugowanie tej przeglądarki”.
Zrzut ekranu paska adresu w Chrome z komunikatem „Rozszerzenie debugera rozpoczęło debugowanie tej przeglądarki”

Elementy iframe w trybie piaskownicy

Jeśli musisz ocenić ciąg znaków jako kod i znajdujesz się w środowisku DOM (np. w skrypcie treści, a nie w skrypcie service worker rozszerzenia), możesz użyć piaskownicy iframe. Rozszerzenia nie obsługują domyślnie takich funkcji jakeval() ze względów bezpieczeństwa. Złośliwy kod może zagrażać bezpieczeństwu użytkowników. Jeśli jednak kod jest wykonywany tylko w znanym bezpiecznym środowisku, np. w ramce iframe, która została odizolowana od reszty internetu, ryzyko jest znacznie mniejsze. W tym kontekście można znieść zasadę Content Security Policy, która blokuje używanie funkcji eval, co pozwala na uruchamianie dowolnego prawidłowego kodu JavaScript.

Jeśli masz przypadek użycia, który nie jest objęty tymi informacjami, skontaktuj się z zespołem, korzystając z listy adresowej chromium-extensions, aby uzyskać opinię, lub otwórz nowe zgłoszenie, aby poprosić o wskazówki One Stop Support.

Co zrobić, jeśli nie zgadzasz się z werdyktem

Egzekwowanie zasad może być skomplikowane, a sprawdzanie wymaga ręcznego wprowadzania danych, co oznacza, że zespół Chrome Web Store może czasami zgodzić się na zmianę decyzji dotyczącej weryfikacji. Jeśli uważasz, że podczas weryfikacji popełniono błąd, możesz odwołać się od decyzji o odrzuceniu za pomocą One Stop Support.