Grégory Rocher
CEO e fundador

Como o Chrome 142+ quebrou o fluxo de trabalho de script local e como o corrigimos

O Chrome 142 introduziu novas proteções contra ataques à rede local. Para a maioria dos aplicativos, essa alteração é quase imperceptível. Para nós, ela interrompeu um fluxo de trabalho de desenvolvimento local muito específico e muito comum.

Se você usa o kit inicial do mapa WorkAdventure e seus scripts personalizados pararam de carregar repentinamente do localhost, você não configurou nada incorretamente. O Chrome mudou a forma como trata as solicitações locais provenientes de iframes em sandbox, e nossa abordagem anterior dependia exatamente disso.

Neste artigo, vou explicar o que mudou, por que isso falha (mesmo com cabeçalhos CORS permissivos), a solução temporária que lançamos e a correção de longo prazo que faz com que o desenvolvimento e a produção se comportem da mesma maneira.

Se você deseja apenas a correção

A correção já está disponível no WorkAdventure v1.27.6. Essa correção abre mais possibilidades para scripts locais e, se você quiser se beneficiar dessas possibilidades quando seu script estiver em produção, recomendamos que você:

Atualize o plugin Vite no package.json do seu kit inicial do mapa:

“wa-map-optimizer-vite”: “^1.2”

e execute npm install novamente.

Seus scripts agora serão carregados de uma origem adequada tanto no desenvolvimento quanto na produção, o que também torna o comportamento do CORS muito mais previsível.

O restante do artigo explica o que aconteceu e por que isso corrige o problema.

O que mudou no Chrome 142

O Chrome 142 introduziu efetivamente duas mudanças que são importantes aqui.

1) Um novo prompt de permissão de “acesso à rede local”

Quando uma página tenta acessar recursos na rede local, por exemplo, localhost, o Chrome agora exige uma decisão explícita do usuário.

No nosso caso, quando o WorkAdventure (hospedado em https://play.workadventu.re) tenta carregar recursos do seu servidor de desenvolvimento local em localhost:5173, o Chrome exibe uma solicitação perguntando se deseja permitir ou negar o acesso à rede local.

Prompt do Chrome solicitando permissão para acessar a rede local (localhost)

Essa parte é fácil de resolver. Basta clicar em Permitir e seguir em frente.

2) A mudança significativa: solicitações locais de origens opacas são bloqueadas

A mudança mais significativa é a forma como o Chrome lida com solicitações de rede local provenientes de uma origem que considera não confiável.

Iframes em sandbox criados sem allow-same-origin acabam com uma origem opaca. Na prática, isso geralmente aparece como origin: null. Com o Chrome 142, as solicitações de rede local provenientes de null são bloqueadas muito cedo, antes mesmo que o CORS seja avaliado.

Esse é o detalhe fundamental: mesmo que seu servidor de desenvolvimento envie cabeçalhos CORS permissivos, o Chrome pode bloquear a solicitação antes que esses cabeçalhos tenham importância.

Por que isso interrompeu o fluxo de trabalho do kit inicial do mapa

O kit inicial do mapa WorkAdventure foi projetado para iterações rápidas.

Quando você executa:

$ npm run dev

Um servidor de desenvolvimento é iniciado em localhost:5173. O WorkAdventure carrega mapas, imagens, JavaScript, CSS e outros recursos desse servidor, para que você veja as alterações em tempo real.

Para recursos de mapas, a nova solicitação de permissão do Chrome geralmente é suficiente para continuar. Mas os scripts são especiais no WorkAdventure.

Os scripts são executados em iframes em sandbox por padrão

O WorkAdventure permite que você escreva scripts personalizados para adicionar interatividade usando a API de script. Por motivos de segurança, esses scripts do usuário não são executados no contexto principal do WorkAdventure. Em vez disso, eles são executados dentro de iframes em sandbox.

Antes do Chrome 142, nosso fluxo de desenvolvimento local era assim:

  1. O WorkAdventure cria um iframe vazio com sandbox=“allow-scripts” (sem allow-same-origin)

  2. Ele usa srcdoc para injetar um pequeno documento HTML nesse iframe

  3. Esse documento inclui uma tag apontando para o seu servidor de desenvolvimento, por exemplo, http://localhost:5173/my-script.js

  4. O navegador busca o script do localhost e o executa dentro do iframe em sandbox

Diagrama: script local carregado em iframe sandbox antes e depois do Chrome 142+

Após o Chrome 142, a etapa 4 falha.

O que você verá quando houver falha

Quando o script é bloqueado, ele nunca é carregado e o Chrome registra erros como:

> O acesso ao script em ‘http://localhost:5173/src/main.ts ‘ da origem ‘null’ foi bloqueado pela política CORS: a permissão foi negada para esta solicitação acessar o espaço de endereço desconhecido.

Nesse ponto, o servidor de desenvolvimento está funcionando, seu código está correto e os cabeçalhos CORS não ajudam. A solicitação é negada anteriormente no pipeline devido ao bloqueio de acesso à rede local.

Primeira correção: desbloquear o desenvolvimento local com um endpoint proxy

Para desbloquear rapidamente os desenvolvedores, alteramos a forma como o WorkAdventure carrega os scripts do usuário durante o desenvolvimento local.

O servidor WorkAdventure agora expõe um endpoint proxy:

/local-script?script=XXX

Em vez de permitir que o iframe em sandbox busque o script diretamente do localhost, o WorkAdventure o busca por meio desse endpoint. Isso faz com que a solicitação tenha origem no servidor WorkAdventure, e não em null.

“Isso não é um problema de segurança?”

Pode ser, dependendo de como for implementado. Nós o definimos com rigor.

Esse endpoint permite apenas scripts hospedados no localhost. Portanto, embora ele permita o carregamento de “qualquer” script local, um invasor precisaria ter acesso ao computador do usuário para hospedar algo mal-intencionado no localhost. Essa é uma barreira muito mais alta e, se um invasor já tiver acesso local, o sistema estará efetivamente comprometido de qualquer forma.

Essa solução corrigiu a quebra imediata do Chrome 142. Mas ela introduziu outro problema.

A desvantagem oculta: o desenvolvimento e a produção não são mais compatíveis

Com a abordagem proxy, o desenvolvimento local mudou a origem efetiva do script.

No desenvolvimento, os scripts agora estavam sendo carregados de um iframe cuja origem é https://play.workadventu.re (o servidor WorkAdventure). Mas na produção, os scripts ainda eram carregados usando srcdoc, de modo que a origem do iframe permanecia nula.

Essa incompatibilidade pode causar problemas difíceis de diagnosticar.

Se um script depender da execução em uma origem real com mais privilégios, por exemplo, acesso a cookies, localStorage ou recursos com escopo de origem atendidos pelo WorkAdventure, ele poderá funcionar localmente e, em seguida, falhar após a implantação.

Por isso, decidimos ir além e corrigir a raiz da inconsistência.

A solução de longo prazo: dar aos scripts uma origem real em todos os lugares

Queríamos uma propriedade acima de tudo: os scripts deveriam ser carregados da mesma forma no desenvolvimento e na produção.

Usar /local-script na produção não era uma opção. Um proxy de produção que pode servir scripts arbitrários hospedados pelo WorkAdventure para o código do usuário seria um grande risco de segurança, com possível acesso a APIs internas e dados do usuário.

Em vez disso, nos apoiamos em algo que já era verdade sobre os mapas da WorkAdventure.

Onde os mapas estão hospedados hoje

Os mapas do WorkAdventure são hospedados:

  • no GitHub Pages, para configurações legadas
  • ou no servidor de armazenamento de mapas do WorkAdventure

Isso nos deu um caminho limpo: hospedar uma página HTML junto com o script e carregar essa página no iframe usando um URL src normal.

Por que isso é seguro o suficiente

Na oferta de SaaS, o servidor de armazenamento de mapas usa um domínio por mundo. Isso isola os scripts por mundo do cliente no nível do domínio.

Em configurações auto-hospedadas, o servidor de armazenamento de mapas geralmente está no mesmo domínio do WorkAdventure ou em um domínio dedicado controlado pelo mesmo administrador. Nesse contexto, o proprietário do mapa e o administrador do servidor geralmente são a mesma pessoa, portanto, isso não introduz um novo risco entre locatários.

O que mudamos no kit inicial do mapa

O kit inicial do mapa é fornecido com um plug-in Vite responsável pela criação de scripts. Estendemos esse plug-in para que ele também gere uma pequena página HTML para cada script, que carrega o script por meio de uma tag tag.

Por exemplo, se você tiver um script chamado my-script.js, o plug-in gerará my-script.html desta forma:

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="https://play.workadventu.re/iframe_api.js"></script>
    <script src="my-script.js"></script>
</head>
<body>
</body>
</html>

O WorkAdventure carrega a página HTML no iframe usando src, em vez de injetar srcdoc e tentar obter o script diretamente do host local.

O resultado é exatamente o que queríamos:

  • uma origem adequada no desenvolvimento
  • uma origem adequada na produção
  • comportamento consistente em todos os ambientes

Como bônus, os scripts que antes tinham dificuldades com os recursos protegidos por CORS agora são, em geral, muito mais fáceis de entender.

Encerramento

O Chrome 142 não adicionou apenas uma solicitação de permissão. Ele também alterou a forma como as solicitações de rede local de origens opacas, como iframes em sandbox com origin: null, são tratadas. Isso quebrou um padrão comum de carregamento de scripts locais durante o desenvolvimento.

Enviamos uma solução alternativa de curto prazo para desbloquear o desenvolvimento local e, em seguida, implementamos uma abordagem mais robusta: carregar scripts por meio de páginas HTML dedicadas hospedadas junto com os mapas, para que os scripts tenham uma origem real tanto no desenvolvimento quanto na produção.

Se estiver usando o kit inicial de mapas, a atualização do wa-map-optimizer-vite para a versão ^1 .2 deve permitir que você volte a ter um fluxo de trabalho tranquilo, com menos surpresas de origem e CORS ao longo do caminho.

You may also be interested in