Postępowanie w przypadku naruszeń kodu hostowanych zdalnie

Kod hostowany zdalnie (RHC) w Chrome Web Store nazywa się wszelkiego rodzaju wykonywanego przez przeglądarkę, która wczytuje się z innego miejsca niż pliki rozszerzenia. Takie usługi jak JavaScript i WASM. Nie obejmuje on danych ani takich elementów jak JSON czy CSS.

Dlaczego RHC nie jest już dozwolone?

Rozszerzenia na platformie Manifest V3 muszą teraz wiązać w pakiecie cały kod, którego używają w samym rozszerzeniu. Wcześniej można było dynamicznie wstrzykiwać tagi skryptu z dowolnego adresu URL w internecie.

Poinformowano mnie, że moje rozszerzenie ma numer RHC. Co się dzieje?

Jeśli podczas sprawdzania rozszerzenie zostało odrzucone z powodu błędu niebieskiego argonu, nasi weryfikatorzy uważają, że używa ono kodu hostowanego zdalnie. Dzieje się tak zazwyczaj wtedy, gdy rozszerzenie próbuje dodać tag skryptu z zasobem zdalnym (tj. z otwartej sieci, a nie z plików w rozszerzeniu) lub pobiera zasób w celu jego bezpośredniego wykonania.

Jak rozpoznać RHC

Znalezienie RHC nie jest trudne, gdy wiadomo, czego szukać. Najpierw sprawdź, czy w projekcie nie ma ciągów „http://” lub „https://”. Jeśli widzisz naruszenie RHC, łatwiej Ci będzie je zlokalizować. Jeśli masz pełny system kompilacji lub używasz zależności z npm bądź innych źródeł zewnętrznych, upewnij się, że przeszukujesz skompilowaną wersję kodu, ponieważ to właśnie ona jest oceniana przez magazyn. Jeśli nadal nie możesz znaleźć problemu, skontaktuj się z zespołem pomocy One Stop. Będzie on mógł wskazać konkretne naruszenia i dowiedzieć się, co jest potrzebne do jak najszybszego opublikowania rozszerzenia.

Co zrobić, jeśli biblioteka prosi o kod

Niezależnie od pochodzenia kodu nie może on zawierać RHC. Dotyczy to kodu, który nie został przez Ciebie utworzony, ale może służyć jako zależność w projekcie. Ten problem wystąpił u niektórych deweloperów korzystających z Firebase, gdy w Uwierzytelnianiu Firebase znajdował się kod zdalny. Mimo że jest to biblioteka własna (tj. należąca do Google), w przypadku RHC nie ma wyjątku. Musisz skonfigurować kod w taki sposób, aby usunąć RHC albo zaktualizować twój kod, tak aby nie zawierał go na początku. Jeśli napotkasz problem, w którym to nie Twój kod ładujący RHC, ale biblioteka, z której korzystasz, najlepiej skontaktować się z jej autorem. Powiadom ich o tym i poproś o obejście problemu lub aktualizację kodu, aby go usunąć.

Co zrobić, jeśli nie możesz doczekać się aktualizacji biblioteki

Niektóre biblioteki wysyłają aktualizację niemal natychmiast po powiadomieniu, ale inne mogą zostać porzucone lub rozwiązanie problemu może zająć trochę czasu. W zależności od tego, co dzieje się w przypadku danego naruszenia, nie musisz czekać, aż zostaną odblokowane, i przejść weryfikację. Masz do wyboru wiele opcji, które pozwalają szybko wznowić pracę.

Kontrola kodu

Czy masz pewność, że potrzebny jest kod powodujący żądanie? Jeśli można usunąć kod lub bibliotekę, która go powoduje, można usunąć, a następnie skasuj ten kod – nie wystarczy.

A może jest inna biblioteka, która oferuje te same funkcje? Poszukaj opcji, które pasują do tych samych przypadków użycia, na stronie npmjs.com, GitHubie lub w innych witrynach.

Drżenie drzew

Jeśli kod powodujący naruszenie RHC nie jest faktycznie używany, może zostać automatycznie usunięty za pomocą narzędzia. Nowoczesne narzędzia do tworzenia, takie jak webpack, Rollup i Vite, mają funkcję potrząsania drzewami. Po włączeniu w systemie kompilacji drżenie drzew powinno usunąć wszystkie nieużywane ścieżki kodu. Może to oznaczać, że masz nie tylko bardziej zgodną wersję kodu, ale także wolniejszą i szybszą. Pamiętaj, że nie wszystkie biblioteki da się potrząsnąć, ale wiele z nich tak się dzieje. Niektóre narzędzia, takie jak Rollup i Vite, mają domyślnie włączone drżenie drzew. Aby można było włączyć pakiet internetowy, trzeba go skonfigurować. Jeśli w ramach rozszerzenia nie używasz systemu kompilacji, ale korzystasz z bibliotek kodu, zdecydowanie zalecamy sprawdzenie, czy dodano narzędzie do kompilacji do swojego przepływu pracy. Narzędzia do tworzenia pomagają pisać bezpieczniejsze, bardziej niezawodne i łatwiejsze w utrzymaniu projekty.

Szczegóły dotyczące wdrożenia mechanizmu hakowania drzew zależą od konkretnego projektu. Oto prosty przykład z usługą o pełnym zakresie: możesz dodać mechanizm hakowania drzew w kodzie projektu. Jeśli np. masz plik o nazwie main.js, który loguje się tylko do Uwierzytelniania Firebase:

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

Potem wystarczy przekazać usłudze Rollup plik wejściowy, wtyczkę do wczytywania plików węzłów @rollup/plugin-node-resolve i nazwę generowanego pliku wyjściowego.

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

Gdy uruchomisz to polecenie w oknie terminala, otrzymasz wygenerowaną wersję naszego pliku main.js, skompilowaną w jeden plik o nazwie compiled.js.

Podsumowywanie może być proste, ale można je też bardzo konfigurować. Możesz dodawać wszelkiego rodzaju złożone logiki i konfiguracje. Zapoznaj się z ich dokumentacją. Dodanie tego typu narzędzi do kompilacji zmniejsza rozmiar i efektywność kodu, a w tym przypadku rozwiązuje problem z kodem hostowanym zdalnie.

Automatyczne edytowanie plików

Coraz bardziej powszechnym sposobem wpisania kodu hostowanego zdalnie do bazy kodu jest jego subdeepencja. Jeśli biblioteka X chce pobrać import bibliotekę Y z sieci CDN, musisz ją zaktualizować, aby ładowała się ze źródła lokalnego. Nowoczesne systemy kompilacji pozwalają w prosty sposób tworzyć wtyczki do wyodrębniania zdalnych odwołań i wbudować je bezpośrednio w kod.

Trzeba by było, że jeśli kod wygląda tak:

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

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

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 pochodził z naszego kodu, zależności, subzależności czy innej lokalizacji.

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

Ręczne edytowanie plików

Najprostszym sposobem jest usunięcie kodu, który powoduje wystąpienie RHC. Otwórz go w wybranym edytorze tekstu i usuń wiersze naruszające zasady. Zazwyczaj nie jest to zalecane, ponieważ jest łamliwe i można je zapomnieć. Utrudnia to obsługę projektu, gdy plik o nazwie „library.min.js” nie jest właściwie Library.min.js. Zamiast edytować nieprzetworzone pliki, łatwiejszym rozwiązaniem jest skorzystanie z narzędzia takiego jak patch-package. Jest to niezwykle zaawansowana opcja, która pozwala zapisywać modyfikacje w pliku zamiast w samym pliku. Zasada opiera się na plikach poprawek, takich jak systemy kontroli wersji, takie jak Git czy Subversion. Musisz tylko ręcznie zmodyfikować kod naruszający zasady, zapisać plik diff i skonfigurować pakiet poprawek ze zmianami, które chcesz zastosować. Pełny samouczek możesz przeczytać w pliku readme projektu. Jeśli instalujesz poprawkę w projekcie, zdecydowanie zalecamy skontaktowanie się z nim i poproszenie o wprowadzenie zmian na początku działania projektu. Zarządzanie poprawkami znacznie ułatwia zarządzanie, ale nie ma nic do naprawienia.

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

W miarę rozrastania się baz kodu zależności (lub zależności) mogą utrzymać ścieżki kodu, które nie są już używane. Jeśli jedna z tych sekcji zawiera kod do wczytywania lub wykonywania RHC, trzeba ją usunąć. Nie ma znaczenia, czy jest ona nieaktywna czy nieużywana. Jeśli nie jest używana, należy ją usunąć przez potrząsanie drzewem lub poprawienie biblioteki.

Czy jest jakieś obejście?

Ogólnie rzecz biorąc, nie. RHC jest niedozwolone. Istnieje jednak niewielka liczba przypadków, w których jest dozwolone. Prawie zawsze są to sytuacje, w których nie można zastosować żadnej innej opcji.

Interfejs User Scripts API

Skrypty użytkownika to niewielkie fragmenty kodu dostarczane zwykle przez użytkownika. Są one przeznaczone dla menedżerów skryptów użytkowników, takich jak TamperMonkey czy Englishmonkey. Nie mają możliwości łączenia kodu napisanego przez użytkowników w pakiet, więc interfejs User Script API udostępnia sposób wykonywania kodu udostępnionego przez użytkownika. Nie zastępuje on chrome.scripting.executeScript ani innych środowisk wykonywania kodu. Aby móc wykonywać dowolne działania, użytkownicy muszą włączyć tryb programisty. Jeśli zespół sprawdzający Chrome Web Store stwierdzi, że produkt jest używany niezgodnie z przeznaczeniem (np. poprzez podanie kodu przez użytkownika), możemy odrzucić produkt lub usunąć informacje o produkcie ze sklepu.

chrome.debugger

Interfejs chrome.debugger API umożliwia rozszerzeniom interakcję z protokołem Chrome Devtools. Jest to ten sam protokół, który jest używany w Narzędziach deweloperskich w Chrome i wielu innych narzędziach. Dzięki temu rozszerzenie może żądać i wykonywać kodu zdalnego. Podobnie jak skrypty użytkownika, nie zastępuje on chrome.scripting i jest znacznie ciekawszy dla użytkowników. Podczas używania aplikacji użytkownik widzi pasek ostrzegawczy u góry okna. Jeśli baner zostanie zamknięty, 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 trybie piaskownicy

Jeśli chcesz 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 też użyć elementu iframe w trybie piaskownicy. Ze względów bezpieczeństwa rozszerzenia nie obsługują domyślnie takich funkcji jak eval(). Złośliwy kod może narazić na bezpieczeństwo użytkowników. Jeśli jednak kod jest wykonywany tylko w znanym bezpiecznym środowisku, np. w elemencie iframe umieszczonym w piaskownicy od reszty sieci, ryzyko to jest znacznie ograniczone. W tym kontekście można zrezygnować z polityki bezpieczeństwa treści, która blokuje użycie oceny, i uruchomić dowolny prawidłowy kod JavaScript.

Jeśli Twój przypadek użycia nie został omówiony, skontaktuj się z zespołem, korzystając z listy adresowej chromium-extensions, aby uzyskać opinię, lub utwórz nowe zgłoszenie, aby poprosić o wskazówki pomocy kompleksowej usługi.

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

Egzekwowanie zasad może być zróżnicowane, a weryfikacja wymaga ręcznego wprowadzania danych. Oznacza to, że zespół Chrome Web Store może czasami zgodzić się zmienić decyzję dotyczącą weryfikacji. Jeśli uważasz, że podczas sprawdzania aplikacji popełniono błąd, możesz odwołać się od decyzji o odrzuceniu, korzystając z pomocy One Stop.