Yarn é muito seguro
Tim Kadlec
25 de outubro de 2016
0 minutos de leituraHá algumas semanas, o Facebook anunciou o lançamento de código aberto do Yarn: um novo cliente para o registro do npm. Embora algumas pessoas tenham manifestado preocupação, ele parece ser um ótimo exemplo de desenvolvimento de código aberto. Facebook, Google, Exponent e Tilde enfrentavam desafios semelhantes ao usar o cliente padrão do npm. Em vez de cada um tentar resolver o problema por conta própria, eles se uniram e desenvolveram a solução a partir do npm. O resultado é um cliente alternativo que oferece melhorias importantes sem abrir mão dos recursos do registro npm subjacente.
O Yarn se apresenta como “ultrarrápido”, “superconfiável” e “mega seguro”. Embora seja verdade que o Yarn costuma ser muito mais rápido e que o novo arquivo de lock garante mais consistência na instalação da sua aplicação, as alegações de segurança são um pouco exageradas.
O que o Yarn faz pela segurança
Quando o Yarn afirma ser “mega seguro”, está se referindo ao uso de somas de verificação para confirmar que o pacote solicitado é o mesmo que você recebe, sem nenhuma modificação.
Verificação de somas de verificação
Você pode ver isso na prática abrindo o arquivo yarn.lock em um dos seus projetos. Veja um trecho:
O trecho acima mostra que solicitamos o pacote moment, que foi resolvido para a seguinte URL:
A parte que merece atenção especial é o trecho após o hash:
Essa é a soma de verificação do arquivo, calculada com o Secure Hash Algorithm 1 (SHA-1). Se você baixar o pacote pelo URL para sua máquina, poderá verificar a soma de verificação na linha de comando usando o comando sha1sum no Linux ou o comando shasum no Mac OSX.
Esses comandos exibem o hash SHA-1, que corresponde ao hash no arquivo de política. Agora, digamos que você solicite esse pacote, mas que ele seja diferente do que está indicado pela soma de verificação no arquivo yarn.lock. Por exemplo, adicionei uma linha ao arquivo README.md, recriei o arquivo .tgz e executei shasum novamente. O novo hash foi:
Esse novo hash não é igual ao esperado, então você pode perceber que algo mudou: o que você solicitou não corresponde ao que recebeu. Esse algo pode ser inofensivo — talvez tenha ocorrido um erro na transmissão do arquivo e ele tenha sido corrompido. Mas também pode ser algo malicioso: talvez alguém tenha obtido o pacote e o adulterado. A soma de verificação avisa que algo deu errado, permitindo que você investigue.
Como invasores podem adulterar um pacote?
Garantir a integridade dos dados é, sem dúvida, um recurso útil, mas vale perguntar como um invasor conseguiria adulterar um pacote.
Uma possibilidade é modificar o pacote na origem, no registro que o hospeda. A maioria das pessoas baixa pacotes de npmjs.com, que, até onde sei, nunca teve casos de invasores modificando código diretamente no registro.
A outra possibilidade é modificar o pacote durante o download. Novamente, a maioria dos pacotes é baixada do registro público do npm, que usa HTTPS. Embora seja possível modificar pacotes em trânsito por HTTPS, isso está longe de ser simples.
As somas de verificação são mais úteis quando você hospeda seu próprio repositório. Embora as soluções da Artifactory e da Nexus sejam bem protegidas, se você criar a sua própria solução, pode haver brechas que permitam adulterar pacotes diretamente no registro. E, embora recomendemos com muita ênfase que você não faça isso, já vimos registros locais servidos por HTTP. Nesses casos, modificar o pacote é muito mais fácil, o que torna as somas de verificação bem mais importantes.
Se você usa o registro público do npm ou hospeda o seu próprio por HTTPS com uma solução comercial, a adulteração contra a qual as somas de verificação protegem deixa de ser uma preocupação tão grande. É um recurso de segurança, mas secundário.
yarn.lock para fixar versões
Além disso, o próprio arquivo yarn.lock traz uma complicação para seus planos de segurança. Assim como o npm shrinkwrap, o objetivo do arquivo yarn.lock é fixar versões específicas das suas dependências. A vantagem de usar um arquivo de lock é que, se eu instalar um projeto Yarn na minha máquina e, amanhã, instalar a mesma aplicação em um ambiente de produção, sei que as duas instalações usarão exatamente as mesmas dependências — mesmo que uma nova versão tenha sido lançada.
Isso é ótimo para manter a consistência, mas os arquivos de lock tendem a impedir a atualização dos pacotes usados. Ao contrário do uso de faixas semver, a única forma de atualizar uma dependência para uma nova versão é editar ou recriar o arquivo de lock. Agora, cabe aos desenvolvedores acompanhar as atualizações que possam incluir correções para vulnerabilidades críticas — mais do que nas abordagens baseadas em semver, como a usada em package.json.
Isso não quer dizer que você não deva usar arquivos de lock. Use-os se a consistência for importante para sua aplicação, mas lembre-se de que será necessário adotar os processos certos para revisar e atualizar ativamente os pacotes vulneráveis.
O elo de segurança que falta
As somas de verificação adicionam uma camada de segurança, mas não garantem que o pacote original que você quer obter seja seguro. No mundo do desenvolvimento de código aberto, esse é um problema bem maior. Embora a maioria das pessoas que mantém projetos de código aberto tenha boas intenções, raramente esses pacotes são desenvolvidos com a segurança como requisito fundamental. Quando incorporamos esses pacotes aos nossos projetos, fazemos isso às cegas — sem entender bem todas as dependências envolvidas nem os problemas de segurança que podem estar escondidos nelas.
Por exemplo, o pacote moment que vimos antes contém uma vulnerabilidade de negação de serviço por expressão regular para a qual existe uma correção. Instalar o pacote com o Yarn não vai nos avisar disso. Verificar dependências em busca de vulnerabilidades conhecidas é um problema de segurança diferente — e maior — do que aquele que o Yarn resolve.
Como ter segurança de verdade?
Felizmente, como o Yarn foi desenvolvido com base no npm, ele se integra bem ao ecossistema. O Yarn ainda tem alguns problemas, mas, à medida que forem resolvidos, as ferramentas de segurança existentes deverão funcionar com poucas alterações.
Por exemplo, para corrigir vulnerabilidades conhecidas em pacotes npm, recomendamos atualmente executar snyk protect como parte da etapa post-install das suas aplicações Node.js. Se você executar yarn install, essa etapa também será acionada e snyk protect continuará sendo executado para verificar suas dependências em busca de vulnerabilidades conhecidas.
Achamos o Yarn muito legal e, a julgar pela atenção que recebeu, muita gente parece concordar. Em geral, ele é mais rápido, e os novos arquivos de lock serão úteis para muitas organizações que buscam mais consistência nas instalações.
É ótimo ver o Yarn tentando incorporar segurança desde o início, mas a confiança ao afirmar que ele é “mega seguro” é um pouco exagerada. O problema não são as somas de verificação, mas o marketing. Elas ajudam a garantir a integridade dos seus dados, mas esse é um problema relativamente secundário no ecossistema Node.js. Muito mais importante é garantir que as dependências sejam seguras desde o começo.
Comece a resolver desafios de capture the flag
Aprenda a resolver desafios de capture the flag assistindo sob demanda ao nosso workshop virtual introdutório.