Um site criado por IA pode abrir login, checkout, documentação ou prévias em outra janela. Também pode ser aberto por um serviço externo que espera manter uma referência em window.opener. Esses fluxos parecem simples até uma política de isolamento separar as janelas em grupos diferentes e a integração perder o canal que usava.
Cross-Origin-Opener-Policy, ou COOP, permite que a resposta do documento defina como ele compartilha um grupo de contextos de navegação com páginas de outras origens. A política pode reduzir a superfície de ataques entre janelas e participa do isolamento necessário para APIs sensíveis, mas não deve ser adicionada sem inventariar pop-ups e retornos.
Este guia mostra como escolher uma COOP, testar login e pagamento, usar report-only e verificar a versão publicada.
Entenda a fronteira que COOP altera
Uma página aberta com window.open() pode receber uma referência para a janela que a abriu. A página original também recebe uma referência para a janela nova. A política de mesma origem já limita o que uma origem acessa da outra, mas algumas propriedades e relações entre os contextos continuam observáveis.
COOP atua no nível do grupo de contextos. Quando a navegação exige uma troca de grupo, referências entre janelas podem parecer fechadas ou deixar de oferecer a relação esperada.
Isso é diferente de:
rel="noopener", aplicado a um link ou abertura específica;postMessage, que define um protocolo explícito entre janelas;- CSP
frame-ancestors, que controla quem pode incorporar uma página; iframe sandbox, que restringe capacidades do documento incorporado;- CORS, que controla a leitura de respostas pelo JavaScript.
O HTML Living Standard define os valores e as trocas de grupo de COOP. Use a especificação como fonte de comportamento; mensagens do console são apenas evidência de uma execução.
Inventarie quem abre e quem é aberto
Procure links, chamadas de JavaScript, SDKs e retornos de autenticação:
rg -n \ 'window\.open|target=["'"']_blank|opener|postMessage|BroadcastChannel|oauth|checkout|popup' \ src publicPara cada fluxo, registre:
página que inicia a abertura:origem da página inicial:URL e redirects da janela aberta:origem final:quem precisa de window.opener:mensagens enviadas e recebidas:como o sucesso é confirmado no backend:comportamento quando a janela fecha:política COOP de cada resposta:fallback sem referência entre janelas:Inclua SDKs que criam pop-ups internamente. A ausência de window.open no código do projeto não prova que login, pagamento ou suporte não dependem de uma janela auxiliar.
Revise também janelas nomeadas. Um código pode reutilizar uma janela com window.open(url, "pagamento"), criando dependência entre navegações que não aparece em links com _blank.
Escolha o valor pelo fluxo necessário
As opções centrais são:
| Valor | Intenção prática |
|---|---|
unsafe-none |
mantém o comportamento padrão, sem isolamento solicitado por COOP |
same-origin-allow-popups |
isola navegações incompatíveis, preservando mais compatibilidade com certos pop-ups |
same-origin |
separa documentos cross-origin em outro grupo e é a base para isolamento completo |
Não escolha same-origin apenas porque parece mais forte. Se um login ou checkout cross-origin depende de window.opener, a mudança pode interromper o retorno mesmo que a interface do provedor continue abrindo.
same-origin-allow-popups existe para cenários em que a página precisa manter determinadas relações com pop-ups que não adotaram uma política equivalente. Trate-o como uma decisão de compatibilidade específica, não como substituto automático de same-origin.
O padrão sem header é unsafe-none. Isso não significa que a página está vulnerável por definição nem que COOP é necessária em toda landing page. A política deve responder a um modelo de ameaça, a relações entre janelas ou a uma necessidade real de isolamento cross-origin.
Comece com report-only quando houver pop-ups
COOP possui um header de observação:
Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="coop"Reporting-Endpoints: coop="https://relatorios.exemplo/coop"O modo report-only ajuda a descobrir acessos que seriam afetados sem aplicar a troca de grupo naquele momento. Use um endpoint controlado, retenção curta e filtros para não transformar relatórios em coleta indiscriminada.
A orientação de rollout do W3C WebAppSec descreve tipos de violação relacionados a opener e openee. Correlacione cada relatório com uma ação reproduzível; não afrouxe a política apenas porque houve volume.
Teste pelo menos:
- abrir e concluir login;
- cancelar login e fechar a janela;
- iniciar e retornar de checkout;
- abrir documentação ou suporte;
- receber mensagens de sucesso e erro;
- navegar por redirects intermediários;
- repetir o fluxo com bloqueador de pop-ups;
- executar o fallback sem
window.opener.
Report-only não prova que o fluxo final está correto em todos os navegadores. Depois de corrigir dependências, aplique a política em um ambiente controlado e repita a matriz.
Não use window.opener como prova de autenticação
Uma janela pode informar que terminou o fluxo, mas o frontend não deve aceitar essa mensagem como prova final de login, pagamento ou autorização.
Se houver postMessage, valide:
window.addEventListener("message", (event) => { if (event.origin !== "https://conta.exemplo") return; if (event.source !== popup) return; if (event.data?.type !== "login-complete") return;
void confirmarSessaoNoBackend();});Origem, janela e schema reduzem mensagens indevidas. A confirmação do estado crítico continua no servidor. O guia de uso seguro de postMessage detalha esse protocolo.
Para links comuns, mantenha a proteção local descrita no guia de reverse tabnabbing. COOP amplia a fronteira da resposta inteira, enquanto noopener expressa a intenção de uma abertura específica.
Combine com COEP somente quando houver motivo
Cross-Origin-Opener-Policy: same-origin participa do isolamento cross-origin, mas não o completa sozinho. Um documento também precisa de uma Cross-Origin-Embedder-Policy compatível e de um contexto seguro para que crossOriginIsolated possa se tornar verdadeiro.
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corpEssa combinação pode ser necessária para recursos como SharedArrayBuffer e temporização de maior precisão. Ela também altera o carregamento de recursos e documentos externos. Não ative COEP para “completar” a configuração antes de inventariar imagens, fontes, scripts, workers, frames e APIs.
O guia de Cross-Origin-Embedder-Policy mostra essa segunda metade e os impactos de require-corp e credentialless.
Entregue o header na resposta real
COOP é um header de resposta HTTP:
Cross-Origin-Opener-Policy: same-originUma meta tag não substitui esse header. Um arquivo com o nome _headers também não produz efeito por existir dentro do pacote.
O contrato atual de Publicação envia os arquivos preparados pelo projeto, mas não interpreta _headers como configuração da resposta. Se a aplicação precisa de COOP, confirme uma camada autorizada que entregue o header no HTML, como uma origem ou proxy administrado pela equipe ou suporte explícito da plataforma.
Registre a limitação como requisito de infraestrutura quando essa camada ainda não existe. Não marque a tarefa como concluída com base apenas no repositório.
Verifique a URL final e cada domínio
Depois do deploy, confira a resposta:
curl -sS -D - -o /dev/null https://exemplo.sitenoar.app \ | rg -i '^cross-origin-opener-policy:'No navegador, repita os fluxos e registre:
console.table({ crossOriginIsolated, hasOpener: window.opener !== null,});crossOriginIsolated: false não demonstra falha de COOP isoladamente; COEP, contexto seguro, Permissions Policy e recursos carregados também participam do resultado. Verifique headers e comportamento separadamente.
Repita na URL padrão e em cada domínio próprio ativo. A origem muda com esquema, host e porta, e um fluxo que funciona em preview pode usar uma allowlist ou redirect incompatível com o endereço final.
Quando ajustar headers ou integrações, gere uma nova versão e republique o mesmo Site para preservar o endereço já aprovado.
Prompt copiável para o agente
Revise e proponha uma Cross-Origin-Opener-Policy para este site.
Pasta publicável: [caminho]URL de teste: [URL]Domínios finais: [lista]Login, checkout e pop-ups: [lista]
- Inventarie window.open, target=_blank, janelas nomeadas, SDKs e redirects.- Registre quem depende de opener, openee, postMessage ou BroadcastChannel.- Compare unsafe-none, same-origin-allow-popups e same-origin.- Comece com report-only quando houver relações entre janelas.- Teste sucesso, cancelamento, fechamento e fallback de cada pop-up.- Não trate mensagens da janela como prova final de autenticação ou pagamento.- Combine com COEP somente se houver requisito de isolamento cross-origin.- Confirme que o header é entregue na resposta HTTP real.- Verifique URL padrão, domínios próprios e todos os redirects.- Entregue política escolhida, incompatibilidades e evidências.Checklist final
- links, pop-ups, SDKs e janelas nomeadas foram inventariados;
- origens e redirects de cada fluxo estão documentados;
- dependências de
window.openerepostMessagesão explícitas; - o valor de COOP atende ao fluxo e ao modelo de ameaça;
- report-only foi analisado antes do enforcement quando necessário;
- login, checkout, cancelamento e fallback foram testados;
- estados críticos são confirmados no backend;
- COEP não foi ativada sem inventário de recursos;
- o header aparece na resposta HTTP final;
- URL padrão e domínios próprios foram verificados;
- a versão publicada corresponde à política aprovada.
COOP não é um selo genérico de segurança. É uma decisão sobre quais páginas podem permanecer no mesmo grupo de navegação e quais integrações precisam atravessar essa fronteira por um protocolo explícito e testado.
