Lidar com violações de código hospedados remotamente

O código hospedado remotamente, ou RHC, é o que a Chrome Web Store chama de tudo que é executado pelo navegador carregado de algum lugar que não seja os próprios arquivos da extensão. Coisas como JavaScript e WASM. Ela não inclui dados ou itens como JSON ou CSS.

Por que o RHC não é mais permitido?

Com o Manifest V3, as extensões agora precisam agrupar todo o código que estão usando dentro da própria extensão. Antes, era possível injetar tags de script dinamicamente de qualquer URL na Web.

Fui informado que minha extensão tem RHC. O que está acontecendo?

Se a extensão foi rejeitada durante a revisão com um erro Blue Argon, nossos revisores acreditam que ela está usando código hospedado remotamente. Isso geralmente é o resultado de uma extensão que tenta adicionar uma tag de script com um recurso remoto (ou seja, da Web aberta, em vez dos arquivos incluídos na extensão) ou buscando um recurso para executar diretamente.

Como identificar o RHC

Identificar o RHC não é particularmente difícil depois que você sabe o que procurar. Primeiro, verifique as strings "http://" ou "https://" no seu projeto. Se houver uma violação do RHC, você provavelmente poderá localizá-la. Se você tiver um sistema de build completo ou usar dependências do NPM ou de outras origens de terceiros, pesquise a versão compilada do código, já que ela está sendo avaliada pela loja. Se ainda assim você não encontrar o problema, a próxima etapa é entrar em contato com o suporte único. Ele poderá descrever as violações específicas e o que é necessário para publicar a extensão o mais rápido possível.

O que fazer se uma biblioteca estiver solicitando o código

Não importa a origem do código, não é permitido ter RHC. Isso inclui um código que você não criou, mas usou apenas como uma dependência no seu projeto. Alguns desenvolvedores que usam o Firebase tiveram esse problema quando o código remoto estava sendo incluído para uso no Firebase Auth. Mesmo que essa fosse uma biblioteca primária (ou seja, do Google), nenhuma exceção é fornecida para o RHC. Você precisa configurar o código para remover o RHC ou atualizar o projeto para não incluir o código inicial. Se você encontrar uma biblioteca que você esteja usando, mas não seu código que está carregando o RHC, mas sim uma biblioteca que você está usando, a melhor solução é entrar em contato com o autor da biblioteca. Informe que isso está acontecendo e peça uma solução alternativa ou atualizações de código para removê-lo.

E se você não puder esperar por uma atualização da biblioteca

Algumas bibliotecas enviam uma atualização quase imediatamente após serem notificadas, mas outras podem ser abandonadas ou demorar um pouco para resolver o problema. Dependendo do que está acontecendo na violação específica, talvez não seja necessário esperar que a migração seja desbloqueada e a análise seja concluída. Há várias opções disponíveis para voltar a funcionar rapidamente.

Auditar o código

Você tem certeza de que o código que está causando a solicitação é necessário? Se ele puder apenas ser excluído ou se uma biblioteca que estiver causando ele puder ser removida, exclua esse código e o job estará pronto.

Como alternativa, existe outra biblioteca que oferece os mesmos recursos? Confira npmjs.com, GitHub ou outros sites para outras opções que atendam aos mesmos casos de uso.

Árvore tremendo

Se o código que causa a violação do RHC não estiver sendo usado, ele poderá ser excluído automaticamente pelas ferramentas. Ferramentas de build modernas, como webpack, Rollup e Vite, entre outras, têm um recurso chamado tree-shaking. Depois de ativado no sistema de build, o tree shaking remove todos os caminhos de código não utilizados. Isso pode significar que você não só tem uma versão do seu código mais compatível, mas também uma mais enxuta e mais rápida. É importante notar que nem todas as bibliotecas podem ser shaking, mas muitas são. Algumas ferramentas, como Rollup e Vite, têm o tree shaking ativado por padrão. O webpack precisa estar configurado para ser ativado. Se você não estiver usando um sistema de build como parte da extensão, mas estiver usando bibliotecas de código, é recomendável investigar a adição de uma ferramenta de build ao fluxo de trabalho. Ferramentas de build ajudam você a escrever projetos mais seguros, confiáveis e de fácil manutenção.

Os detalhes de como implementar o treehaking dependem do seu projeto específico. Mas, usando um exemplo simples com o Rollup, você pode adicionar o treehaking apenas compilando o código do projeto. Por exemplo, se você tiver um arquivo chamado main.js que só faz login no 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);
  }
});

Depois, basta informar ao Rollup o arquivo de entrada, um plug-in necessário para carregar arquivos de nó @rollup/plugin-node-resolve e o nome do arquivo de saída gerado por ele.

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

Ao executar esse comando em uma janela de terminal, você receberá uma versão gerada do nosso arquivo main.js, todos compiladas em um único arquivo chamado compiled.js.

A consolidação pode ser simples, mas também é muito configurável. Você pode adicionar todos os tipos de lógica e configuração complexas. Basta conferir a documentação. A adição de ferramentas de build como essa resulta em um código menor e mais eficiente e, nesse caso, corrige o problema de código hospedado remotamente.

Editar arquivos automaticamente

Uma maneira cada vez mais comum de o código hospedado remotamente entrar na base de código é como uma subdependência de uma biblioteca que você está incluindo. Se a biblioteca X quiser import a biblioteca Y de uma CDN, ainda será necessário atualizá-la para que ela seja carregada de uma fonte local. Com sistemas de build modernos, é possível criar plug-ins para extrair uma referência remota e incorporá-la diretamente ao código.

Isso significa que o código fornecido é parecido com este:

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

Você poderia criar um pequeno plug-in de visualização completa.

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

Depois de executar o build com o novo plug-in, cada URL import remoto será descoberto, independentemente de ter sido ou não nosso código, uma subdependência, subdependência ou qualquer outro lugar.

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

Editar arquivos manualmente

A opção mais simples é excluir o código que está causando o RHC. Abra o editor de texto de sua preferência e exclua as linhas que violam a política. Isso geralmente não é tão aconselhável, porque é frágil e pode ser esquecido. Isso dificulta a manutenção do projeto quando um arquivo chamado "library.min.js" não realmente é library.min.js. Em vez de editar os arquivos brutos, uma opção um pouco mais sustentável é usar uma ferramenta como o patch-package. Essa é uma opção superpoderosa que permite salvar modificações em um arquivo, em vez do próprio arquivo. Ele é criado com base em arquivos de patch, o mesmo tipo de recurso usado em sistemas de controle de versões, como Git ou Subversion (links em inglês). Basta modificar manualmente o código violador, salvar o arquivo diff e configurar o patch-package com as alterações que você quer aplicar. Leia um tutorial completo no leia-me do projeto. Se você estiver aplicando um patch a um projeto, recomendamos que entre em contato com o projeto para solicitar que as alterações sejam feitas. Embora o patch-package facilite muito o gerenciamento de patches, não ter nada para corrigir é ainda melhor.

O que fazer se o código não estiver sendo usado

À medida que as bases de código crescem, as dependências (ou dependência de uma dependência, ou dependência de...) podem manter caminhos de código que não são mais usados. Se uma dessas seções incluir código para carregar ou executar o RHC, terá que ser removida. Não importa se ele está inativo ou não é usado. Se ela não estiver sendo usada, ela precisará ser removida por uma árvore ou um patch da biblioteca para que ela seja removida.

alguma solução alternativa?

De modo geral, não, o RHC não é permitido. No entanto, há um pequeno número de casos em que isso é permitido. Esses são quase sempre casos em que é impossível para qualquer outra opção.

API User Scripts

Os scripts de usuário são pequenos snippets de código geralmente fornecidos pelo usuário e destinados a gerenciadores de scripts, como TamperMonkey e encontramoper (em inglês). Esses gerenciadores não podem agrupar códigos gravados pelos usuários. Por isso, a API User Script expõe uma maneira de executar o código fornecido pelo usuário. Ele não substitui chrome.scripting.executeScript ou outros ambientes de execução de código. Os usuários precisam ativar o modo de desenvolvedor para executar tudo. Se a equipe de revisão da Chrome Web Store acreditar que o item está sendo usado de uma maneira diferente da pretendida (por exemplo, código fornecido pelo usuário), ele poderá ser rejeitado ou será removido da loja.

chrome.debugger

A API chrome.debugger permite que as extensões interajam com o protocolo do Chrome Devtools. Esse é o mesmo protocolo usado para Devtools do Chrome e um número incrível de outras ferramentas. Com ela, uma extensão pode solicitar e executar código remoto. Assim como os scripts de usuário, ele não substitui o chrome.scripting e oferece uma experiência do usuário muito mais notável. Enquanto ele estiver em uso, o usuário verá uma barra de aviso na parte superior da janela. Se o banner for fechado ou dispensado, a sessão de depuração será encerrada.

Captura de tela da barra de endereço no Chrome com a mensagem "A extensão do depurador começou a depurar este navegador"
Captura de tela da barra de endereço no Chrome com a mensagem "A extensão do depurador começou a depurar este navegador"

Iframes no modo sandbox

Se você precisar avaliar uma string como código e estiver em um ambiente DOM (por exemplo, um script de conteúdo, em vez de um service worker de extensão), outra opção é usar um iframe no modo sandbox. Como medida de segurança, as extensões não oferecem suporte a itens como eval() por padrão. O código malicioso pode colocar a segurança do usuário em risco. No entanto, quando o código é executado apenas em um ambiente seguro conhecido, como um iframe que foi colocado no sandbox do restante da Web, esses riscos são bastante reduzidos. Nesse contexto, a Política de Segurança de Conteúdo que bloqueia o uso de eval pode ser removida, permitindo que você execute qualquer código JavaScript válido.

Se você tem um caso de uso que não é coberto, entre em contato com a equipe usando a lista de e-mails chromium-extensions para receber feedback ou abra um novo tíquete para solicitar orientação do Suporte único.

O que fazer se você discordar de um veredito

A aplicação das políticas pode ser diferenciada, e a revisão envolve entrada manual, o que significa que a equipe da Chrome Web Store às vezes pode concordar em mudar uma decisão de análise. Se você acredita que um erro foi cometido na análise, conteste a rejeição usando o suporte único.