HeatMapXHeatMapX
PreçosEntrar

Pré-visualizando sites externos com segurança — implementação de proxy + sanitização + iframe sandbox

HeatMapX Engineering Team5 min read
  • engineering
  • security
  • nextjs
  • iframe

Resumo deste artigo

  • Carregar um site externo em um iframe da própria origem traz o risco de o JS externo acessar a sessão do serviço
  • A defesa é em camadas: "proxy com proteção contra SSRF + remoção de JS externo + CSP restritivo + iframe sandbox"
  • Um sandbox forte demais pode até bloquear os próprios scripts internos. Esquecer de incluir allow-scripts foi uma armadilha que fez a funcionalidade parar de funcionar

O teste A/B do HeatMapX conta com uma funcionalidade que permite "pré-visualizar a aparência após a alteração (Variant B), já aplicada à página de destino". Tecnicamente, isso significa "exibir o site externo do usuário, com segurança, dentro de um iframe do próprio domínio do serviço" — um processo surpreendentemente delicado. Neste artigo, compartilhamos o design da solução e as armadilhas que encontramos na prática.

Por que uma implementação ingênua é perigosa

Se buscarmos o HTML do site externo e o servirmos diretamente pela própria origem (por exemplo, heatmapx.com), qualquer <script> ou onclick= presente nesse HTML passa a ser executado com os privilégios da própria origem. Isso abre a possibilidade de leitura de cookies e sessões de login. É algo que precisamos evitar a todo custo.

Estrutura de defesa em camadas

Para isso, empilhamos as seguintes camadas.

1. Proxy com proteção contra SSRF

Validamos a URL de destino e rejeitamos qualquer esquema que não seja http/https. Além disso, bloqueamos localhost, IPs privados e endpoints de metadados de nuvem (como 169.254.169.254). Os redirecionamentos não são seguidos automaticamente: usamos redirect: 'manual' para revalidar cada salto individualmente, evitando que o fluxo seja direcionado para a rede interna.

2. Remoção do JS externo (sanitização)

Removemos as tags <script>, os manipuladores inline on*= e o esquema javascript: do HTML obtido. Não há necessidade de executar o JS do site do cliente na pré-visualização (é uma limitação conhecida que SPAs não sejam totalmente reproduzidas).

3. CSP restritivo e base href

Inserimos um <base href> logo após o <head> para resolver caminhos relativos de imagens e CSS, e aplicamos à resposta um CSP restritivo que impede a execução de JS externo. Imagens e CSS são permitidos, pois são necessários para a exibição.

4. iframe sandbox

Por fim, isolamos o lado da exibição adicionando o atributo sandbox ao iframe.

A armadilha: o sandbox estava restritivo demais

Na pré-visualização, injetamos no HTML obtido um pequeno script interno que "aplica a alteração (changeSet)" e o executamos dentro do iframe para modificar a aparência. Porém, o sandbox do iframe de pré-visualização estava configurado apenas com allow-same-origin, sem o allow-scripts.

Como resultado, nosso próprio script também deixava de ser executado, causando um bug em que a página original era exibida sem a alteração ser aplicada. O iframe do lado do editor de edição, configurado corretamente com allow-scripts allow-same-origin, funcionava normalmente — a causa era essa divergência de configuração entre os dois.

A correção foi simples: bastou alinhar o lado da pré-visualização também para allow-scripts allow-same-origin. Junto com isso, adicionamos um teste de regressão que valida o atributo sandbox do iframe.

sandbox="allow-same-origin"  →  sandbox="allow-scripts allow-same-origin"

Lições aprendidas

  • Pense na incorporação de conteúdo externo como uma "defesa em camadas". Não confie em uma única medida.
  • O sandbox não é seguro só por estar presente — o essencial é conceder exatamente os privilégios necessários, nem mais, nem menos. Se for restritivo demais, pode até travar a própria funcionalidade.
  • Sempre que houver "dois fluxos que fazem o mesmo processo" (como o editor e a pré-visualização), verifique se os atributos de segurança estão alinhados entre eles. Corrigir apenas um lado pode quebrar o outro.

Conclusão

É possível implementar uma pré-visualização segura de sites externos combinando proteção contra SSRF, remoção de JS externo, CSP restritivo e iframe sandbox em camadas de defesa. E os privilégios do sandbox trazem problemas tanto quando são insuficientes quanto quando são excessivos. O esquecimento do allow-scripts neste caso foi um exemplo clássico disso.

Heatmaps no Claude Code — comece grátis.

Cole uma tag de tracking e receba análises e sugestões CRO via CLI.