Skip to main content

Como manter as dependências npm do seu projeto

Escrito por
Headshot of José Pérez Rivas

José Pérez Rivas

Vul costs feature

11 de junho de 2020

0 minutos de leitura

É muito comum encontrarmos projetos que funcionam corretamente em produção, mas já não recebem manutenção ativa: estão em produção, funcionam e o cliente considera o projeto concluído.

Infelizmente, isso não é totalmente verdade. Costumamos esquecer que, quando um projeto está concluído e em produção, isso não significa que ele não precise de manutenção. A maioria dos projetos ainda precisa ser revisada, e os incidentes devem ser resolvidos quando ocorrem. Se fizéssemos uma comparação com a compra de um veículo, seria mais ou menos assim: vamos à concessionária, escolhemos o modelo certo, pagamos e aproveitamos o veículo enquanto ele for útil, sem fazer nenhuma manutenção periódica, certo? Claro que não — e o mesmo vale para o software.

Ao desenvolver projetos de API REST ou aplicações de linha de comando com Node.js, é muito comum usar o gerenciador de pacotes de dependências de código aberto npm para incluir frameworks e ferramentas nesses projetos.

Até certo ponto, isso é vantajoso, pois pode ajudar a reduzir o tempo de desenvolvimento. Incluir pacotes estáveis, bem testados e mantidos pela comunidade atende a algumas necessidades do projeto. No entanto, isso também pode acabar se voltando contra nós e se tornar um problema.

A seguir, discutimos um cenário comum em um projeto Node.js. Alguns desses problemas surgem quando deixamos um projeto sem acompanhamento e sem manutenção evolutiva e preventiva.

Caso específico

Imagine um projeto de API REST com Node.js que está em produção há 2 anos ou mais. Durante esses dois anos, ninguém tomou nenhuma medida para atualizar ou adaptar as dependências às novas versões. No desenvolvimento, o pacote express foi usado como framework base para a funcionalidade CRUD. Além disso, a biblioteca jsonwebtoken foi usada para gerar tokens de segurança, e o moment, para internacionalizar datas.

Possíveis problemas

O uso de bibliotecas de dependência relativamente novas pode ser considerado o primeiro problema, pois baseamos parte da nossa solução em um software que não foi testado pela comunidade e que, possivelmente, não tem uma evolução constante.

Em segundo lugar, basear parte da nossa solução em bibliotecas com “um único contribuidor”, como eu as chamo. Essas dependências são desenvolvidas por uma única pessoa, responsável por lançar melhorias, fazer a manutenção e resolver incidentes e, por fim, decidir unilateralmente o rumo desse software. Essas dependências nos limitam bastante.

Como terceiro problema, temos as dependências que contêm outras dependências. No entanto, isso não é visível à primeira vista, no que costumamos chamar de “Node Module Hole”.

Janela do Visual Studio Code mostrando a estrutura de arquivos de um projeto Node.js e um terminal aberto.

Fonte: https://github.com/JoseJPR/tutorial-nodejs-snyk-vuln-cost/blob/master/assets/video.gif

Veja aqui mais dicas sobre o assunto.

Algumas soluções

1. Eu realmente preciso dessa dependência?

Em um projeto Node.js, o primeiro lugar onde devemos buscar informações é a própria documentação. A documentação da API do Node.js traz vários exemplos práticos do que podemos fazer por conta própria, usando a API do Node.js de forma “nativa”, sem dependências externas.

2. Use microdependências

Depois de confirmar que precisamos de um recurso para atender às necessidades do projeto, precisamos encontrar a opção certa. À primeira vista, muitas vezes pensamos que a primeira opção exibida nos resultados de uma busca no Google (ou no mecanismo de busca do npm) será a mais adequada, mas, em muitos casos, não é. Precisamos parar, pensar e analisar quanto do que essa biblioteca faz realmente precisamos. Talvez ela faça muito mais do que precisamos, trazendo para o projeto uma biblioteca que, em grande parte, ficará sem uso.

Análise de mercado

Precisamos pesquisar um pouco e buscar alternativas: o ecossistema npm é muito amplo e podemos encontrar diferentes bibliotecas que fazem praticamente a mesma coisa. Mas qual escolher? Nesse caso, podemos usar ferramentas online como Bundlephobia, que compara o tamanho de cada pacote, ou npmtrends, que compara informações como volume de downloads e contribuições da comunidade, entre outros parâmetros.

Essas ferramentas podem ajudar a escolher a dependência certa. Informações como o tamanho da dependência, o volume da comunidade que a mantém, o número de versões lançadas nos últimos meses ou a quantidade de downloads podem ser indicadores importantes.

4. Use ferramentas preventivas

A Snyk lançou a extensão de código aberto Vuln Cost para o Visual Studio Code, que permite visualizar de forma simples e rápida quantas vulnerabilidades há no nosso software a partir do arquivo package.json e até mesmo de cada arquivo que contém a importação de uma biblioteca.

Atualmente, em um projeto Node.js, podemos injetar dependências por meio de require e import, adicionando-as por completo ou parcialmente, se isso for permitido. Na imagem a seguir, você pode ver um exemplo claro de como isso funciona usando o projeto descrito anteriormente (express + jsonwebtoken + moment):

Janela do Visual Studio Code mostrando um projeto Node.js, com arquivos-fonte no explorador e um terminal aberto.

Fonte: https://github.com/JoseJPR/tutorial-nodejs-snyk-vuln-cost/blob/master/assets/video.gif

Se você quer mais recursos sobre como usar o Vuln Cost, confira os três vídeos abaixo:

Conclusões

Um dos desafios que o setor de software sempre enfrentou é explicar e fazer o usuário final entender que o software tem uma necessidade básica: receber manutenção e evoluir, buscando, por exemplo, adaptar-se às atualizações do sistema operacional, melhorar o desempenho ou eliminar possíveis pontos vulneráveis.

Outro desafio é conseguir tempo para que as equipes de desenvolvimento possam refletir, atualizar conhecimentos e se capacitar para encontrar as alternativas mais adequadas ao desenvolver software — a primeira opção que aparece nem sempre é a certa.

As quatro soluções que exploramos acima podem ajudar você a desenvolver uma base de código sustentável, de alta qualidade, escalável e mais segura.

Comece a jogar Capture the Flag

Aprenda a resolver desafios de Capture the Flag assistindo sob demanda ao nosso workshop virtual introdutório.

Leia mais

Blog

Modelos de ponta encontraram as vulnerabilidades. Só o atacante encontrou as cadeias.

A análise estática encontrou as falhas, mas só os testes de ataque em aplicações ativas provaram como elas poderiam ser encadeadas para causar invasões. Uma comparação entre Evo COS, Claude Security e Claude Code Security.

feature insights context
Blog

Os ataques autônomos já chegaram. A defesa precisa acompanhar o ritmo.

Os atacantes autônomos estão reduzindo o tempo disponível para a defesa. Saiba como a descoberta, a correção, a validação e a prevenção contínuas ajudam as equipes de segurança a acompanhar esse ritmo.

Blog

Por que agentes de programação com IA continuam criando falhas de controle de acesso

Agentes de programação com IA podem gerar uma lógica de autorização que compila e passa pela revisão, mas permite que um tenant acesse os dados de outro. Saiba por que é difícil detectar falhas de controle de acesso e como evitá-las.