Como ganhar segurança e privacidade com o particionamento do cache

Em geral, o armazenamento em cache pode melhorar o desempenho ao armazenar dados para que solicitações futuras dos mesmos dados sejam atendidas mais rapidamente. Por exemplo, um recurso armazenado em cache da rede pode evitar uma ida e volta ao servidor. Um resultado computacional armazenado em cache pode omitir o tempo para fazer o mesmo cálculo.

No Chrome, o mecanismo de cache é usado de várias maneiras, e o cache HTTP é um exemplo.

Como o cache HTTP do Chrome funciona atualmente

A partir da versão 85, o Chrome armazena em cache os recursos buscados da rede usando os respectivos URLs de recursos como a chave de cache. Uma chave de cache é usada para identificar um recurso em cache.

O exemplo a seguir ilustra como uma única imagem é armazenada em cache e tratada em três contextos diferentes:

Chave de cache: https://x.example/doge.png
Chave de cache: { https://x.example/doge.png }

Um usuário acessa uma página (https://a.example) que solicita uma imagem (https://x.example/doge.png). A imagem é solicitada da rede e armazenada em cache usando https://x.example/doge.png como chave.

Chave de cache: https://x.example/doge.png
Chave de cache: { https://x.example/doge.png }

O mesmo usuário visita outra página (https://b.example), que solicita a mesma imagem (https://x.example/doge.png). O navegador verifica o cache HTTP para saber se ele já tem esse recurso armazenado em cache, usando o URL da imagem como chave. O navegador encontra uma correspondência no cache e, portanto, usa a versão em cache do recurso.

Chave de cache: https://x.example/doge.png
Chave de cache: { https://x.example/doge.png }

Não importa se a imagem é carregada em um iframe. Se o usuário visitar outro site (https://c.example) com um iframe (https://d.example) e o iframe solicitar a mesma imagem (https://x.example/doge.png), o navegador ainda poderá carregar a imagem do cache, porque a chave do cache é a mesma em todas as páginas.

Esse mecanismo tem funcionado bem em termos de desempenho por muito tempo. No entanto, o tempo que um site leva para responder a solicitações HTTP pode revelar que o navegador acessou o mesmo recurso no passado, o que o expõe a ataques de segurança e privacidade, como estes:

  • Detectar se um usuário visitou um site específico: um invasor pode detectar o histórico de navegação de um usuário verificando se o cache tem um recurso que pode ser específico para um site ou grupo específico.
  • Ataque de pesquisa entre sites: um invasor pode detectar se uma string arbitrária está nos resultados da pesquisa do usuário verificando se uma imagem "sem resultados da pesquisa" usada por um site específico está no cache do navegador.
  • Rastreamento entre sites: o cache pode ser usado para armazenar identificadores semelhantes a cookies como um mecanismo de rastreamento entre sites.

Para reduzir esses riscos, o Chrome vai particionar o cache HTTP a partir da versão 86.

Como a partição do cache afeta o cache HTTP do Chrome?

Com o particionamento de cache, os recursos em cache vão ser codificados usando uma nova "Chave de isolamento de rede", além do URL do recurso. A chave de isolamento de rede é composta pelo site de nível superior e pelo site do frame atual.

Confira novamente o exemplo anterior para saber como a partição de cache funciona em contextos diferentes:

Chave de cache { https://a.example, https://a.example, https://x.example/doge.png}
Chave de cache: { https://a.example, https://a.example, https://x.example/doge.png }

Um usuário visita uma página (https://a.example) que solicita uma imagem (https://x.example/doge.png). Nesse caso, a imagem é solicitada da rede e armazenada em cache usando uma tupla que consiste em https://a.example (o site de nível superior), https://a.example (o site de frame atual) e https://x.example/doge.png (o URL do recurso) como chave. Quando a solicitação de recurso é do frame de nível superior, o site de nível superior e o site de frame atual na chave de isolamento de rede são iguais.

Chave de cache { https://a.example, https://a.example, https://x.example/doge.png}
Chave de cache: { https://b.example, https://b.example, https://x.example/doge.png }

O mesmo usuário visita uma página diferente (https://b.example) que solicita a mesma imagem (https://x.example/doge.png). Embora a mesma imagem tenha sido carregada no exemplo anterior, como a chave não corresponde, não haverá um acerto de cache.

A imagem é solicitada da rede e armazenada em cache usando uma tupla que consiste em https://b.example, https://b.example e https://x.example/doge.png como chave.

Chave de cache { https://a.example, https://a.example, https://x.example/doge.png}
Chave de cache: { https://a.example, https://a.example, https://x.example/doge.png }

Agora o usuário volta para https://a.example, mas desta vez a imagem (https://x.example/doge.png) está incorporada em um iframe. Nesse caso, a chave é uma tupla que contém https://a.example, https://a.example e https://x.example/doge.png e ocorre uma ocorrência de cache. Observe que, quando o site de nível superior e o iframe são o mesmo site, o recurso armazenado em cache com o frame de nível superior pode ser usado.

Chave de cache { https://a.example, https://a.example, https://x.example/doge.png}
Chave de cache: { https://a.example, https://c.example, https://x.example/doge.png }

O usuário está de volta em https://a.example, mas desta vez a imagem está hospedada em um iframe de https://c.example.

Nesse caso, a imagem é transferida por download da rede porque não há um recurso no cache que corresponda à chave composta por https://a.example, https://c.example e https://x.example/doge.png.

Chave de cache { https://a.example, https://a.example, https://x.example/doge.png}
Chave de cache: { https://a.example, https://c.example, https://x.example/doge.png }

E se o domínio tiver um subdomínio ou um número de porta? O usuário visita https://subdomain.a.example, que incorpora um iframe (https://c.example:8080), que solicita a imagem.

Como a chave é criada com base em "scheme://eTLD+1", os subdomínios e os números de porta são ignorados. Portanto, ocorre uma ocorrência em cache.

Chave de cache { https://a.example, https://a.example, https://x.example/doge.png}
Chave de cache: { https://a.example, https://c.example, https://x.example/doge.png }

E se o iframe for aninhado várias vezes? O usuário visita https://a.example, que incorpora um iframe (https://b.example), que incorpora outro iframe (https://c.example), que finalmente solicita a imagem.

Como a chave é tirada do frame superior (https://a.example) e do frame imediato que carrega o recurso (https://c.example), ocorre uma ocorrência em cache.

Perguntas frequentes

Ela já está ativada no meu Chrome? Como posso confirmar?

O recurso será lançado até o fim de 2020. Para verificar se a sua instância do Chrome já oferece suporte a ele:

  1. Abra chrome://net-export/ e pressione Start Logging to Disk (Iniciar geração de registros no disco).
  2. Especifique onde salvar o arquivo de registro no computador.
  3. Navegue na Web usando o Chrome por um minuto.
  4. Volte para chrome://net-export/ e pressione Stop Logging.
  5. Acesse https://netlog-viewer.appspot.com/#import.
  6. Clique em Escolher arquivo e selecione o arquivo de registro salvo.

A saída do arquivo de registro vai aparecer.

Na mesma página, encontre SplitCacheByNetworkIsolationKey. Se for seguido por Experiment_[****], o particionamento de cache HTTP está ativado no Chrome. Se for seguido por Control_[****] ou Default_[****], ele não será ativado.

Como posso testar o particionamento do cache HTTP no meu Chrome?

Para testar o particionamento do cache HTTP no Chrome, você precisa iniciar o Chrome com uma flag de linha de comando: --enable-features=SplitCacheByNetworkIsolationKey. Siga as instruções em Executar o Chromium com flags para aprender a iniciar o Chrome com uma flag de linha de comando na sua plataforma.

Como desenvolvedor da Web, preciso fazer alguma coisa em resposta a essa mudança?

Essa não é uma mudança de interrupção, mas pode impor considerações de desempenho para alguns serviços da Web.

Por exemplo, aqueles que apresentam grandes volumes de recursos altamente armazenáveis em cache em vários sites (como fontes e scripts populares) podem ter um aumento no tráfego. Além disso, quem consome esses serviços pode depender cada vez mais deles.

Há uma proposta para ativar bibliotecas compartilhadas de uma forma que preserve a privacidade, chamada de Bibliotecas compartilhadas da Web (vídeo de apresentação), mas ela ainda está em consideração.

Qual é o impacto dessa mudança comportamental?

A taxa de falha de cache geral aumenta cerca de 3,6%, as mudanças na FCP (First Contentful Paint) são modestas (~0,3%), e a fração geral de bytes carregados da rede aumenta cerca de 4%. Saiba mais sobre o impacto no desempenho na explicação sobre o particionamento de cache HTTP.

Isso é padronizado? Outros navegadores se comportam de maneira diferente?

As "partições de cache HTTP" são padronizadas na especificação de busca, embora os navegadores se comportem de maneira diferente:

Como a busca de trabalhadores é tratada?

Os workers dedicados usam a mesma chave do frame atual. Service workers e workers compartilhados são mais complicados, já que podem ser compartilhados entre vários sites de nível superior. A solução para eles está em discussão.

Recursos