O Chrome desativa a modificação de document.domain

Se o site depender da configuração de document.domain, sua ação será necessária.

O que está mudando e por quê?

A partir do Chrome 115, os sites não poderão definir document.domain: o Chrome vai tornar document.domain imutável. Para se comunicar entre origens, você precisa usar abordagens alternativas, como postMessage() ou a API Channel Messaging.

Essa mudança será lançada de forma progressiva.

Esperamos que outros navegadores descontinuem e removam essa funcionalidade. Consulte a seção Compatibilidade com navegadores para mais detalhes.

Por que tornar document.domain imutável?

document.domain foi projetado para acessar ou definir o nome do host da origem. Muitos sites definem document.domain para permitir a comunicação entre páginas no mesmo site, mas de origem cruzada.

Embora essa seja uma técnica conveniente, ela apresenta um risco de segurança, porque relaxa a política de mesma origem. As preocupações de segurança em relação ao document.domain levaram a uma mudança na especificação que avisa os usuários para que não o usem.

Em detalhes: por que tornar o document.domain imutável?

Como o document.domain é usado hoje

Muitos sites definem document.domain para permitir a comunicação entre páginas no mesmo site, mas de origem cruzada.

Sites do mesmo site, mas de origem cruzada, têm o mesmo eTLD+1, mas subdomínios diferentes.

Confira como o document.domain foi usado até agora:

Digamos que uma página em https://parent.example.com incorpore uma página de iframe de https://video.example.com. Essas páginas têm o mesmo eTLD+1 (example.com) com subdomínios diferentes. Quando o document.domain das duas páginas está definido como 'example.com', o navegador trata as duas origens como se fossem da mesma origem.

Defina document.domain para https://parent.example.com:

// Confirm the current origin of "parent.example.com"
console.log(document.domain);

// Set the document.domain
document.domain = 'example.com';
console.log(document.domain);

Defina document.domain para https://video.example.com:

// Confirm the current origin of "video.example.com"
console.log(document.domain);

// Set the document.domain
document.domain = 'example.com';
console.log(document.domain);

Agora é possível criar uma manipulação de DOM entre origens em https://parent.example.com contra https://video.example.com.

Os sites definem document.domain para que os documentos do mesmo site se comuniquem com mais facilidade. Como essa mudança relaxa a política de mesma origem, a página mãe pode acessar o documento do iframe e percorrer a árvore DOM, e vice-versa.

Essa é uma técnica conveniente, mas que apresenta um risco de segurança.

Problemas de segurança com document.domain

As preocupações de segurança em relação ao document.domain levaram a uma mudança na especificação que alerta os usuários para que não o usem.

Por exemplo, quando duas páginas definem document.domain, elas podem fingir que estão na mesma origem. Isso é particularmente importante quando essas páginas usam um serviço de hospedagem compartilhado com subdomínios diferentes. A configuração document.domain permite o acesso a todos os outros sites hospedados pelo mesmo serviço, o que facilita o acesso dos atacantes aos seus sites. Isso é possível porque document.domain ignora a parte do número da porta do domínio.

Para saber mais sobre as implicações de segurança da configuração de document.domain, leia a página "Document.domain" no MDN.

Compatibilidade com navegadores

Como saber se meu site foi afetado?

Se o site for afetado por essa mudança, o Chrome vai avisar você no painel de problemas do DevTools, que foi adicionado em 2022. Observe a bandeira amarela no canto superior direito das Ferramentas do desenvolvedor.

Captura de tela do aviso do problema no DevTools

Você também pode executar seu site na auditoria de API descontinuada do Lighthouse para encontrar todas as APIs que estão programadas para serem removidas do Chrome.

Se você tiver configurado a API Reporting, o Chrome vai enviar relatórios de descontinuação para notificar você sobre essa descontinuação. Saiba como usar a API Reporting com serviços de coleta de relatórios existentes ou criando sua própria solução interna.

Como posso ver essa mudança em ação?

A mudança será lançada de forma progressiva, começando no Chrome 115. Para conferir essa mudança em ação, mesmo que ela ainda não tenha sido lançada no seu navegador Chrome, ative-a da seguinte maneira:

  1. Abrir chrome://flags/#origin-agent-cluster-default
  2. Selecione Ativar.
  3. Reinicie o Chrome.

Quais alternativas posso usar?

A melhor opção é não modificar document.domain, por exemplo, hospedando a página e todos os frames constituintes na mesma origem. Isso funciona em todas as versões de todos os navegadores. No entanto, isso pode exigir um retrabalho substancial de um aplicativo. Portanto, vale a pena considerar alternativas que continuem oferecendo suporte a acessos entre origens.

Use postMessage() ou a API Channel Messaging em vez de document.domain

Na maioria dos casos de uso, postMessage() ou a API Channel Messaging podem substituir document.domain.

No exemplo a seguir:

  1. https://parent.example.com solicita https://video.example.com em um iframe para manipular o DOM enviando uma mensagem por postMessage().
  2. O https://video.example.com manipula o DOM assim que recebe a mensagem e notifica o sucesso de volta para o pai.
  3. https://parent.example.com reconhece o sucesso.

Em https://parent.example.com:

// Send a message to https://video.example.com
iframe.postMessage('Request DOM manipulation', 'https://video.example.com');

// Receive messages
iframe.addEventListener('message', (event) => {
  // Reject all messages except ones from https://video.example.com
  if (event.origin !== 'https://video.example.com') return;

  // Filter success messages
  if (event.data === 'succeeded') {
    // DOM manipulation is succeeded
  }
});

Em https://video.example.com:

// Receive messages
window.addEventListener('message', (event) => {
  // Reject all messages except ones from https://parent.example.com
  if (event.origin !== 'https://parent.example.com') return;

  // Do a DOM manipulation on https://video.example.com.

  // Send a success message to https://parent.example.com
  event.source.postMessage('succeeded', event.origin);
});

Teste e veja como funciona. Se você tiver requisitos específicos que não funcionem com postMessage() ou a API Channel Messaging, entre em contato pelo Twitter (@ChromiumDev) ou faça uma pergunta no Stack Overflow com uma tag document.domain.

Como último recurso, envie o cabeçalho Origin-Agent-Cluster: ?0.

Se você tiver motivos fortes para continuar definindo document.domain, envie o cabeçalho de resposta Origin-Agent-Cluster: ?0 com o documento de destino.

Origin-Agent-Cluster: ?0

O cabeçalho Origin-Agent-Cluster instrui o navegador se o documento precisa ser processado pelo cluster de agente com origin-key ou não. Para saber mais sobre Origin-Agent-Cluster, leia Como solicitar o isolamento de desempenho com o cabeçalho Origin-Agent-Cluster.

Quando você envia esse cabeçalho, o documento pode continuar definindo document.domain mesmo depois que ele se torna imutável por padrão.

Todos os outros documentos que exigem esse comportamento também precisam enviar um Origin-Agent-Cluster. document.domain não terá efeito se apenas um documento o definir.

Configurar OriginAgentClusterDefaultEnabled para a política empresarial

Como alternativa, o administrador pode configurar a política OriginAgentClusterDefaultEnabled para false para tornar o document.domain configurável por padrão nas instâncias do Chrome em toda a organização. Para saber mais, consulte Gerenciamento e lista de políticas do Chrome Enterprise | Documentação.

Recursos

Agradecimentos

Foto de Finan Akbar no Unsplash