Como lidar com a nova árvore de dependências do npm@3
Remy Sharp
25 de fevereiro de 2016
0 minutos de leituraAté pouco tempo atrás, a ferramenta de linha de comando da Snyk só oferecia suporte ao npm@2. Isso mudou quando lançamos o snyk@1.9.0, com suporte completo às novas estruturas de diretórios do npm@3.
Queremos compartilhar alguns dos desafios técnicos envolvidos e as novas ferramentas que surgiram desse processo.
O que mudou no npm@3
No npm@2, as dependências do Node eram instaladas no diretório node_modules de cada pacote Node. Por exemplo, os diretórios do módulo request ficam assim:
Como você pode ver no trecho acima, node_modules já aparece várias vezes. Isso não é tão ruim, mas pode gerar muita duplicação. Bibliotecas populares, como lodash, podem aparecer muitas e muitas vezes em um mesmo projeto!
Originalmente, o npm@2 fazia um trabalho para eliminar duplicações, mas o npm@3 achata completamente essa estrutura de diretórios com o objetivo de remover toda a duplicação. Com o npm@3, o mesmo pacote request fica assim:
Como você pode ver, a estrutura é completamente diferente, mas, o mais importante, isso não afeta em nada a forma como o Node carrega os módulos.
Como isso afeta a Snyk?
Para começar, foi preciso reescrever completamente a lógica da CLI para percorrer os pacotes. Antes, a Snyk percorria o diretório node_modules, iterava por cada subdiretório e montava uma representação em árvore dos pacotes. Relativamente simples.
Só que agora a estrutura de diretórios plana do npm@3 não representa as relações entre os pacotes. Por exemplo, o pacote async na listagem do npm@3 acima é, na verdade, uma dependência do pacote form-data, que, por sua vez, é uma dependência de request. Mas não dá para ver isso na árvore de arquivos.
Por isso, reescrevemos completamente a resolução de pacotes da Snyk e a extraímos para um módulo independente chamado snyk-resolve-deps (código aberto sob a licença Apache 2).
Esse módulo é usado na CLI do snyk, mas também pode ser instalado como uma ferramenta de CLI independente (a instalação com npm install -g snyk-resolve-deps disponibiliza um utilitário chamado snyk-resolve).
O snyk-resolve-deps percorre primeiro toda a estrutura de diretórios para montar a árvore física. Em seguida, essa árvore é passada para a próxima etapa, que cria uma árvore lógica: a estrutura que representa de onde os pacotes podem ser carregados.
Isso significa que há suporte às estruturas de diretórios do npm@2 e do npm@3, que geram uma árvore virtual como esta:
Em resumo, agora a Snyk oferece suporte aos seus projetos instalados com npm@3 tão bem quanto aos instalados com npm@2. Conseguimos encontrar os caminhos corretos para aplicar patches e identificar com precisão todos os caminhos vulneráveis.
Qual é a diferença em relação ao ‘npm ls’?
Se você conhece as ferramentas do npm, provavelmente já ouviu falar de npm ls, útil para visualizar essas árvores.
A grande diferença entre snyk-resolve-deps e npm ls é que nossa ferramenta mostra a árvore lógica completa e todos os caminhos pelos quais um pacote entrou no seu projeto.
Se analisarmos como request é incluído no código do npm (na branch 2.x), veremos que o npm ls conta uma história (do que está disponível no disco):

Já nosso próprio método de resolução conta outra história. Isso não significa que o npm ls esteja errado; queremos saber exatamente o que está carregando request, e nosso snyk-resolve-deps pode nos dar essa resposta:

Como você pode ver, muito mais pacotes dependem do módulo request do que você imaginava. Se esse pacote tivesse uma vulnerabilidade, agora a Snyk saberia claramente quais são os caminhos vulneráveis.
snyk-resolve-deps
O pacote snyk-resolve-deps já está disponível sob uma licença de código aberto Apache 2. Depois de instalado globalmente, ele fica disponível com o alias snyk-resolve.
O utilitário de CLI oferece diversos filtros e opções, incluindo a visualização --disk (que gera resultados bem parecidos com os de npm ls) e --filter X e --count X, para filtrar e encontrar ocorrências de uma dependência específica. Saiba mais com snyk-resolve --help.
Você pode executar npm install -g snyk hoje mesmo e testar anonimamente qualquer pacote ou repositório do GitHub. Com uma conta gratuita, você também pode começar a monitorar seus projetos em busca de vulnerabilidades.
Comece a jogar Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo sob demanda ao nosso workshop virtual introdutório.