Verificar e eliminar vulnerabilidades em dependências pode ser mais simples do que você imagina e lhe garanto que isso pode salvar seu tempo e te livrar de algumas dores de cabeça no futuro.
Antes de tudo, é importante saber gerenciar as dependências do seu projeto e entender como o seu gerenciador de pacote faz uma parte do trabalho para você, nesse artigo vou abordar os seguintes tópicos:
Table of contents
Antes de falar sobre as vulnerabilidades em si, acho importante uma explicação básica sobre o que significa a sigla SemVer (Semantic Version) e como funciona a relação do package.jsoncom o package-lock.json
SemVer
SemVer, ou Versionamento Semântico, é uma especificação para ajudar desenvolvedores a entender as mudanças e atualizações durante o versionamento de pacote.
Uma versão de pacote é definida em 3 números Major.Minor.Patch (ex: 2.3.14), bom o que significa cada número desse:
- Major (2): Uma versão com atualizações que não tem compatibilidade com versões major anteriores. Então se você atualizar da 1.0 para 2.0 pode ser que isso cause algum problema quando você executar seu projeto, seja por alguma funcionalidade obsoleta ou alguma mudança na sua utilização, etc.
- Minor (2.3): Uma versão que adiciona recursos que tem compatibilidade com versões minor anteriores, ou seja, atualizações dentro da mesma versão major não devem quebrar seu sistema.
- Patch (2.3.14): Normalmente uma versão para lançar correções de bugs, vulnerabilidades e claro mantendo compatibilidade com versões de patch anteriores.
Aqui não tem muito segredo, então quando você ouvir algo do tipo “tal pacote já lançou uma versão de patch(x) pra corrigir aquela vulnerabilidade da V14.3” é uma versão 14.3.x (entenda x como qualquer número).
- Intervalo de versões (^, ~)
Algo fora dessa especificação são os sinais de circunflexo ^ e til ~ , que você comumente verá em projetos, são usados para definir intervalo de versões e sinalizar para o npm como ele deve lidar com as atualizações da dependência.
-
^circunflexo
Permite atualizações até versões minor mas não major, por exemplo: 2.3 pode atualizar para 2.4 mas por conta própria não vai fazer uma atualização de versão para major 3.x
-
~til
Permite atualizações apenas de versões patch dentro da minor especificada, por exemplo: 2.3.14 pode atualizar para 2.3.20. E claro não vai atualizar para uma versão 2.4
Também é possível não especificar um intervalo de versões, dessa forma a instalação é fixada em uma versão e só pode ser alterada manualmente com uso do npm install por exemplo.
Definir um intervalo de versões vai trazer mais segurança e praticidade quando precisar dependências mas caso precise de um controle mais rígido pode travar em uma versão sem problemas.
Relação entre package.json e package-lock.json
São arquivos que se completam.
O package.json salva as dependências do projeto, é onde você vai ter um overview geral e pode definir o intervalo de versões.
O package-lock.json é quem vai controlar a árvore de dependências e definir qual a versão exata que vai ser instalada, claro seguindo a referência definida no package.json, garantindo que todas as instalações tenham as mesmas versões de dependências, por isso é muito importante você manter o package-lock.json commitado/salvo no seu repositório além de deixar processo de instalação mais rápido vai dar consistência entre diferentes ambientes.
Lidando com vulnerabilidades
O npm nos forcene basicamente duas funcionalidades para identificar e resolver vulnerabilidades em nossas dependências.
npm audit e npm audit fix
Para verifica se as versões instaladas das dependências no projeto contém alguma vulnerabilidade conhecida, npm audit eu diria que é o primeiro passo. Executar esse comando no seu terminar vai gerar algo como:

Nesse exemplo estou com a versão 16.1.6 do Next, aqui o relatório indica que nesse projeto só tenho vulnerabilidade nessa dependência e essa versão está dentro de um range de 6 vulnerabilidades conhecidas e como pelo menos uma delas tem gravidade de nível high a gravidade geral é essa, mesmo se algumas delas tiverem nível menor, também retorna links com mais informações sobre elas.
Para eliminar essas vulnerabilidades, como no meu package.json defini o pacote do Next como ^16.1.6 (olha o ^) e existe uma correção para essas vulnerabilidades dentro desse intervalo de versão definido, isso permite que apenas executando npm audit fix ele atualize a dependência para uma versão sem vulnerabilidades.
Aqui foi feita uma atualização para 16.2.4 mas e se tivesse definido com ~ ? Fica aí a lição de casa.
Conclusão
Escrevi esse artigo com o propósito de fixação do conteúdo que estudei e deixo aqui alguns tópicos para se aprofundar sobre o assunto.
- Dependabot
- .npmrc (save-exact, audit-level)
- Snyk
Referências:
https://www.youtube.com/watch?v=kK4Meix58R4
https://semver.org/lang/pt-BR/
https://docs.npmjs.com/cli/v11/configuring-npm/package-lock-json

Top comments (1)
npm audit should be in every ci pipeline. catching vulnerabilities early saves so many headaches down the road.