Um site criado por IA pode ganhar uma biblioteca para animação, outra para formulário e mais algumas para resolver detalhes que o navegador já faria sozinho. O resultado funciona, mas a árvore instalada fica maior do que a equipe imagina — e uma dependência transitiva pode chegar à página sem aparecer diretamente no package.json.

Revisar dependências JavaScript não é contar pacotes nem executar um comando que imprime “zero vulnerabilidades”. É entender o que foi escolhido, qual caminho trouxe cada módulo, se o código chega à build publicada e como uma atualização será testada.

Este guia organiza a revisão da origem ao pacote final, sem tratar alerta automático como prova de exploração nem ausência de alerta como garantia de segurança.

Comece pelo inventário real

Localize os manifests e lockfiles do projeto antes de instalar ou atualizar qualquer coisa:

Terminal window
rg --files -g 'package.json' -g 'bun.lock*' -g 'package-lock.json' -g 'pnpm-lock.yaml' -g 'yarn.lock'

Em um monorepo, uma landing page pode herdar dependências do workspace raiz ou de pacotes internos. Registre:

  • manifest que declara a dependência;
  • versão ou faixa solicitada;
  • lockfile que fixa a resolução;
  • pacote ou aplicação que a utiliza;
  • se entra no navegador, na build, nos testes ou apenas no desenvolvimento;
  • responsável pela escolha e pela próxima revisão.

Inclua também código fora do gerenciador de pacotes: arquivos vendorizados, scripts de CDN e snippets copiados. O guia de scripts de terceiros mostra como inventariar origens, dados e comportamento desses recursos.

Preserve o lockfile antes de investigar

O manifest expressa intenção; o lockfile registra a árvore resolvida. Se o agente apaga ou regenera o lockfile logo no começo, a revisão deixa de comparar a mesma instalação que produziu a versão atual.

Antes de mudar versões:

  1. confirme qual gerenciador o repositório usa;
  2. instale com o modo imutável ou congelado oferecido por ele;
  3. registre falhas de resolução sem trocar de ferramenta;
  4. gere uma build de referência;
  5. salve o diff e os testes que representam o comportamento atual.

Não adicione um segundo lockfile para “fazer o comando funcionar”. Dois resolvedores no mesmo projeto tornam a origem da build ambígua.

Separe dependências diretas e transitivas

Uma dependência direta foi escolhida pelo projeto. Uma transitiva entrou porque outro pacote depende dela. As duas podem afetar a entrega, mas a correção costuma acontecer em lugares diferentes.

Use o comando de árvore do gerenciador adotado pelo projeto e responda, para cada item relevante:

pacote afetado:
versão instalada:
caminho até ele:
dependência direta responsável:
ambiente em que é usado:
chega ao bundle do navegador:
correção disponível:
teste que cobre a atualização:

O Dependency Graph do GitHub também deriva relações de manifests e lockfiles e mostra caminhos transitivos em ecossistemas compatíveis. Ele complementa a árvore local; não substitui a confirmação da build usada para publicar.

Execute a auditoria compatível com o projeto

No ecossistema npm, npm audit consulta o registro configurado e relata vulnerabilidades conhecidas na árvore suportada. A documentação oficial do npm explica que o relatório inclui pacote afetado, severidade, caminho e correções disponíveis quando existem.

Execute o mecanismo de auditoria correspondente ao lockfile real. Depois classifique cada alerta por:

  • pacote e versão afetada;
  • caminho direto ou transitivo;
  • condição descrita no advisory;
  • uso em runtime, build, teste ou ferramenta local;
  • presença do código afetado no fluxo do projeto;
  • versão corrigida e impacto esperado da atualização;
  • evidência necessária para encerrar ou aceitar temporariamente o risco.

Se o comando não suporta o gerenciador ou o registro adotado, registre a lacuna. Não gere um lockfile paralelo apenas para obter um relatório.

Não leia severidade sem contexto

Severidade ajuda a priorizar, mas não responde sozinha se o site está exposto. Um pacote de servidor usado apenas por uma ferramenta local tem um caminho diferente de uma biblioteca que processa entrada não confiável no navegador.

Ao mesmo tempo, “só está em devDependencies” não encerra a análise. Ferramentas de build executam código durante instalação e compilação, e um pacote de desenvolvimento pode transformar os bytes publicados.

Pergunte:

  1. qual ação ou entrada alcança o comportamento vulnerável;
  2. em que ambiente o pacote executa;
  3. se a função afetada é realmente usada;
  4. quais privilégios e dados estão disponíveis;
  5. se a build final contém o código;
  6. se existe mitigação documentada enquanto a correção não chega.

Registre a conclusão com o advisory e o caminho da dependência. Não descarte um alerta apenas porque a página parece estática.

Atualize sem usar força como atalho

Uma correção automática pode alterar várias versões e até introduzir uma mudança incompatível. A própria documentação do npm alerta que algumas remediações exigem revisão manual e que mudanças semver-major podem quebrar a API.

Prefira uma mudança controlada:

  1. atualize a dependência direta que traz o pacote afetado;
  2. mantenha manifest e lockfile no mesmo diff;
  3. leia notas de versão e migração;
  4. execute testes, typecheck e build;
  5. compare o bundle e a jornada que usa a biblioteca;
  6. confira a Version publicada em uma sessão limpa.

Evite --force como resposta automática. Se a única versão corrigida exige migração, trate a migração como trabalho explícito e não como detalhe do auditor.

Remova o que não precisa existir

Uma dependência eliminada não precisa ser atualizada, monitorada ou carregada. Procure:

  • imports que não aparecem mais na aplicação;
  • bibliotecas duplicando APIs do navegador;
  • pacote inteiro usado para uma função pequena;
  • plugin mantido por um framework que já foi removido;
  • dependência presente na raiz mas usada por um único pacote;
  • script remoto e pacote local oferecendo a mesma capacidade.

Remova uma de cada vez, regenere a árvore com o gerenciador correto e teste. Uma ferramenta de detecção de imports não enxerga necessariamente carregamento dinâmico, configuração ou plugins referenciados por nome; revise os resultados antes de apagar.

Verifique origem e integridade quando fizer sentido

Para pacotes publicados com provenance, o npm permite verificar onde e como uma versão foi produzida. A documentação de provenance descreve a inspeção da origem e o comando npm audit signatures para versões compatíveis do CLI.

Provenance não afirma que o código é seguro. Ela ajuda a relacionar o pacote a uma origem e a um processo de publicação. Combine esse sinal com manutenção, advisory, licença, revisão da mudança e necessidade real.

Para arquivos externos imutáveis carregados por CDN, avalie Subresource Integrity. SRI valida bytes específicos no navegador; não substitui a revisão do pacote nem acompanha automaticamente uma nova versão.

Teste o artefato que será publicado

Depois da atualização, gere a build com o mesmo comando do projeto e compare:

  • arquivos e tamanhos produzidos;
  • chunks novos ou removidos;
  • código de terceiros no bundle;
  • requisições abertas pela página;
  • console em carregamento e interação;
  • formulário, navegação, Analytics e consentimento;
  • comportamento quando a integração falha;
  • source maps e arquivos internos que não deveriam sair.

O contrato de Publicação envia HTML e assets preparados pelo projeto. Ele não reaudita dependências nem escolhe versões no momento do upload. A evidência precisa acompanhar a mesma build que entrou no pacote.

Antes de publicar, repita também a busca por chaves e segredos no frontend. Atualizar dependências não corrige uma credencial já incorporada ao JavaScript.

Publique e mantenha a revisão viva

Depois do deploy, abra a URL final e percorra as jornadas afetadas. Registre commit, lockfile, comando de build, alertas analisados e URL verificada.

Novos advisories podem surgir sem qualquer mudança no repositório. Configure uma rotina compatível com o risco do projeto e use alertas contínuos, como Dependabot quando aplicável, para reabrir a análise. “Zero alertas” descreve o banco de dados e a árvore naquele momento; não encerra a manutenção.

Prompt copiável para o agente

Revise as dependências JavaScript deste site sem atualizar nada ainda.
Repositório e branch: [origem]
Aplicação publicável: [caminho]
Comando de build: [comando]
Gerenciador e lockfile autorizados: [valores]
- Inventarie manifests, lockfiles, dependências diretas, transitivas e scripts externos.
- Preserve o lockfile e gere uma build de referência.
- Execute a auditoria compatível com o gerenciador real.
- Para cada alerta, informe caminho, ambiente, condição, alcance e correção.
- Não crie outro lockfile e não use atualização forçada.
- Proponha remoções e atualizações separadamente.
- Depois da aprovação, altere o menor conjunto possível e rode os gates.
- Devolva diff, testes, build e riscos restantes antes de publicar.

Checklist final

  • gerenciador e lockfile confirmados;
  • dependências diretas e transitivas inventariadas;
  • scripts externos e arquivos vendorizados incluídos;
  • build de referência reproduzida;
  • alertas classificados por caminho e uso real;
  • nenhuma correção foi aplicada com força sem revisão;
  • manifest e lockfile mudaram juntos;
  • dependências desnecessárias foram removidas;
  • typecheck, testes e build passaram;
  • bundle e requisições foram comparados;
  • Version publicada corresponde aos arquivos auditados;
  • URL final e próxima revisão foram registradas.

Uma árvore de dependências não fica confiável por ser curta nem por estar atualizada no dia. Ela fica controlável quando cada escolha tem origem, caminho, necessidade, teste e um responsável por revisar a próxima mudança.