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

Eiji Kitamura
Eiji Kitamura

Em geral, o armazenamento em cache pode melhorar o desempenho ao armazenar dados para que solicitações futuras dos mesmos dados sejam atendidas com mais rapidez. Por exemplo, um recurso armazenado em cache da rede pode evitar um retorno de 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 formas, 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 na rede, usando os respectivos URLs de recursos como chave de cache. Uma chave de cache é usada para identificar um recurso armazenado 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 visita uma página (https://a.example) que solicita uma imagem (https://x.example/doge.png). A imagem é solicitada a partir da rede e armazenada em cache usando https://x.example/doge.png como a 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 de HTTP para ver 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 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 de um iframe. Se o usuário acessar 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 de cache é a mesma em todas as páginas.

Esse mecanismo tem funcionado bem em termos de desempenho há 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 anteriormente, o que deixa o navegador suscetível a ataques de segurança e privacidade, como estes:

  • Detectar se um usuário visitou um site específico: um adversário pode detectar o histórico de navegação de um usuário verificando se o cache tem um recurso específico de um determinado site ou coorte de sites.
  • Ataque de pesquisa entre sites: um adversário 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.
  • Acompanhamento entre sites: o cache pode ser usado para armazenar identificadores semelhantes a cookies como um mecanismo de acompanhamento entre sites.

Para reduzir esses riscos, o Chrome particionará o cache HTTP a partir do Chrome 86.

Como o particionamento de cache afeta o cache HTTP do Chrome?

Com o particionamento de cache, os recursos em cache serão 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 o exemplo anterior para saber como o particionamento de cache funciona em diferentes contextos:

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 à 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 do 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 os mesmos.

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, isso não será uma ocorrência em 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 a 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 contendo https://a.example, https://a.example e https://x.example/doge.png, e ocorre uma ocorrência em cache. Quando o site de nível superior e o iframe forem o mesmo, o recurso armazenado em cache com o frame de nível superior poderá 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 a 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á recurso no cache que corresponda à chave que consiste em 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 contiver um subdomínio ou um número de porta? O usuário acessa 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", subdomínios e 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 estiver aninhado várias vezes? O usuário acessa 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 é extraída 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

Ele já está ativado no meu Chrome? Como posso confirmar?

O recurso será lançado até o final de 2020. Para verificar se sua instância do Chrome já é compatível:

  1. Abra chrome://net-export/ e pressione Iniciar registro no disco.
  2. Especifique onde salvar o arquivo de registro no seu 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. Pressione Escolher arquivo e transmita o arquivo de registro que você salvou.

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 estará ativado no Chrome. Se for seguido por Control_[****] ou Default_[****], ele não estará ativado.

Como posso testar o particionamento de cache HTTP no Chrome?

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

Como desenvolvedor da Web, há alguma ação que eu deva tomar em resposta a essa mudança?

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

Por exemplo, empresas que disponibilizam grandes volumes de recursos altamente armazenáveis em cache em muitos sites (como fontes e scripts conhecidos) podem notar um aumento no tráfego. Além disso, os usuários desses serviços podem confiar mais neles.

Há uma proposta para ativar as bibliotecas compartilhadas de maneira a preservar a privacidade, chamada 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 geral de ausência no cache aumenta em cerca de 3,6%, as mudanças na FCP (Primeira exibição de conteúdo) são modestas (aproximadamente 0,3%) e a fração geral de bytes carregados da rede aumenta em 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:

  • Chrome: usa scheme://eTLD+1 de nível superior e scheme://eTLD+1 de frame.
  • Safari: usa o eTLD+1 de nível superior
  • Firefox: planejando implementar com schema://eTLD+1 de nível superior e considerando incluir uma segunda chave, como o Chrome.

Como a busca de workers é tratada?

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

Recursos