Blog · Publicado originalmente em inglês em .
Um arquivo ZIP não é só um monte de dados. São instruções de um estranho sobre onde gravar arquivos e quanta memória usar, e toda biblioteca de descompactação, por padrão, obedece a elas.
Nomes que saem da pasta
Um item do ZIP pode se chamar ../../etc/passwd. Se alguma coisa juntar isso a uma pasta, ele vai parar num lugar que ninguém pretendia. É um problema antigo, que tem até nome, zip slip, e o conselho de sempre é limpar o caminho.
Nós preferimos recusar. Esses nomes viram endereços na própria origem do site, e um nome que teríamos que limpar é um nome que não entendemos. Limpar transforma uma entrada hostil numa entrada plausível. Recusar a transforma numa mensagem que diz qual arquivo era o problema.
Arquivos pequenos que não são pequenos
Quarenta kilobytes podem virar quatro gigabytes ao descompactar. A verificação óbvia, descompactar e depois olhar o tamanho, acontece quando a memória já acabou.
Por isso, toda decisão sobre tamanho é tomada com base nos tamanhos declarados nos próprios cabeçalhos do ZIP, antes de expandir um único byte: o total, cada arquivo, o número de arquivos e a proporção entre compactado e descompactado. Um arquivo de quatro megabytes cheio de zeros fica com menos de sessenta e quatro kilobytes compactado, e é recusado só por essa proporção.
Os tamanhos declarados também são a palavra de um estranho, claro. Mas é uma palavra que dá para conferir quase sem custo, e que só nos causa problema se declarar menos do que há. E isso a leitura em streaming detecta no caminho.
Uma lista do que entra, não do que fica de fora
As extensões que servimos estão numa lista. Todo o resto é recusado pelo nome, com a extensão na mensagem, para a pessoa saber qual arquivo tirar.
Uma lista do que fica de fora seria a promessa de ter pensado em tudo. Não pensamos, e ninguém pensou. Uma hospedagem estática que serve .php não é uma hospedagem estática, e o jeito de ter certeza é dizer o que entra, e não o que fica de fora.
A parte que não era sobre segurança
As pessoas compactam uma pasta, então tudo chega dentro de uma pasta que ninguém queria no endereço. Uma única pasta em comum na raiz é removida. Duas ou mais querem dizer que o ZIP é mesmo organizado assim, e ele fica como está.
E uma pasta sem index.html era um erro. Não é: uma pasta de imagens, ou um relatório e a planilha dele, é uma coisa perfeitamente razoável de querer num link. Nós escrevemos a página em que ela abre: uma lista do que tem dentro, com todos os nomes escapados, porque esses nomes vieram de um estranho e a página é servida da própria origem do site.
Os testes parecem uma lista do que o ZIP de um estranho não tem permissão de dizer. Foi a forma mais útil que encontramos para eles.
Perguntas
O que acontece com um ZIP que tem um nome que sai da pasta?
Ele é recusado. O Solta não limpa o caminho: recusa, com uma mensagem que diz qual arquivo era o problema.
Como o Solta lida com um ZIP pequeno que vira gigabytes ao descompactar?
Toda decisão sobre tamanho usa os tamanhos declarados nos cabeçalhos do próprio ZIP, antes de expandir um único byte: o total, cada arquivo, o número de arquivos e a proporção entre compactado e descompactado. Se o ZIP declarar menos do que há, a leitura em streaming detecta no caminho.
Quais tipos de arquivo de um ZIP são publicados?
Só as extensões que estão numa lista. Todo o resto é recusado pelo nome, com a extensão na mensagem, para você saber qual arquivo tirar.
Por que a pasta de fora não aparece no endereço?
Quem compacta uma pasta faz tudo chegar dentro dela. Uma única pasta em comum na raiz é removida. Se há duas ou mais, o ZIP é mesmo organizado assim, e fica como está.
Uma pasta sem index.html pode ser publicada?
Pode. O Solta escreve a página em que ela abre: uma lista do que tem dentro, com todos os nomes escapados.

