Postępowanie w przypadku naruszeń kodu hostowanych zdalnie

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

Dlaczego RHC nie jest już dozwolone?

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 weryfikacji 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 dołączonych do rozszerzenia) 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 związanych z opieką zdrowotną, prawdopodobnie możesz je znaleźć. 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źć problemu, skontaktuj się z One Stop Support. Będą mogli wskazać konkretne naruszenia i określić, 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. Chociaż była to biblioteka własna (czyli należąca do Google), nie ma wyjątku w przypadku RHC. Musisz skonfigurować kod, aby usunąć RHC, lub zaktualizować projekt, aby nie zawierał kodu. Jeśli napotkasz problem, w którym RHC nie jest ładowany przez Twój kod, ale przez używaną przez Ciebie bibliotekę, najlepszym rozwiązaniem będzie skontaktowanie się z autorem biblioteki. Poinformuj ich o tym i poproś o obejście problemu lub aktualizację kodu, aby go usunąć.

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ć na przeniesienie sprawy do innego zespołu, aby odblokować konto i pomyślnie przejść weryfikację. Dostępnych jest wiele opcji, które pozwolą Ci szybko wrócić do pracy.

Sprawdź kod

Czy masz pewność, że kod powodujący żądanie jest potrzebny? 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.

usuwanie nieużywanego kodu,

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, Rollup i Vite (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ą. Pamiętaj, ż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ę, aby ją włączyć. 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ą tworzyć 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 Rollupem. 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";

browser.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 dodać wszelkiego rodzaju złożoną logikę i konfigurację. Wystarczy, że zapoznasz się z dokumentacją. Dodanie takich narzędzi do kompilacji 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, nadal musisz ją zaktualizować, aby ładował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 jest wykrywany niezależnie od tego, czy jest 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 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 rodzaju plików, które są używane w systemach kontroli wersji, takich 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, bardzo zachęcamy do skontaktowania się z nim i poproszenia o wprowadzenie zmian w górę strumienia. Chociaż patch-package znacznie ułatwia zarządzanie poprawkami, jeszcze lepiej jest nie mieć niczego do poprawienia.

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…) mogą utrzymywać ścieżki kodu, które nie są już używane. Jeśli jedna z tych sekcji zawiera 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?

Ogólnie rzecz biorąc, 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 TamperMonkey i Violentmonkey. 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 funkcji browser.scripting.executeScript ani innych środowisk wykonywania kodu. Aby cokolwiek wykonać, użytkownicy muszą włączyć tryb programisty. 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.

browser.debugger

Interfejs browser.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 on skryptów przeglądarki i ma znacznie większy wpływ na wygodę użytkowników. Podczas korzystania z tej funkcji użytkownik zobaczy u góry okna pasek ostrzegawczy. Jeśli baner zostanie zamknięty lub odrzucony, sesja debugowania zostanie zakończona.

Zrzut ekranu paska 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 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ć elementu iframe w piaskownicy. Rozszerzenia nie obsługują domyślnie takich funkcji jakeval() ze względów bezpieczeństwa. Złośliwy kod może narazić użytkowników na niebezpieczeństwo. 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życie funkcji eval, co pozwala na uruchomienie 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 od 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.