Você instalou um pacote pelo npm, o auditoria do npm parecia estar tudo em ordem, e você seguiu em frente.
Seis meses depois. Você baixa as alterações mais recentes, algo na integração contínua (CI) apresenta um erro e agora você precisa de uma resposta clara sobre uma dependência: será que o tslib é realmente um problema nesta árvore? Vasculhar todo o relatório de auditoria em busca dessa única resposta é um trabalho desnecessário.
O npm moderno pode responder a essa pergunta de forma mais direta. Você pode consultar a árvore de dependências com um seletor de vulnerabilidades e filtrar dados estruturados de auditoria com jqou recorrer a ferramentas simples do terminal quando precisar apenas de uma análise superficial. Assim, você pode rastrear exatamente por que o pacote está instalado.
Aqui estão quatro maneiras de verificar um único pacote do npm, na ordem em que você deve recorrer a elas.
Observação: os comandos abaixo foram testados no npm 10.9.7 e no npm 12.0.1. Os seletores e os formatos de saída podem mudar entre versões principais do npm; portanto, execute npm -v antes de incorporar qualquer uma dessas instruções em um script.
1. Consultar o pacote diretamente com npm query
npm query percorre sua árvore de dependências instaladas usando seletores de dependência no estilo CSS. Dois deles são responsáveis por isso aqui: #tslib corresponde a pacotes chamados tslibe :vuln restringe os resultados a instâncias com um aviso conhecido.
npm query '#tslib:vuln'
Um array vazio significa que o npm não encontrou nenhuma instância desse pacote que correspondesse a um aviso conhecido na árvore e nos dados do registro que consultou. Um array preenchido significa que encontrou, e cada entrada contém metadados detalhados do pacote e da árvore de dependências, além de um campo de localização que indica onde essa cópia está localizada na pasta node_modules.
Esse conjunto de metadados contém muito JSON para uma única pergunta. Reduza-o com jq:
npm query '#tslib:vuln' | jq '.[] | {location, version, advisories: [.queryContext.advisories[] | {severity, title}]}'
A seletor :vuln seletor anexa todos os avisos correspondentes ao nó sob queryContext.advisories, de modo que você obtém a gravidade, o título, a pontuação CVSS, o CWE e o intervalo de versões vulneráveis sem precisar de um segundo comando – e você obtém todos eles, não apenas o primeiro.
É possível filtrar por gravidade dentro do seletor, o que ajuda quando a árvore apresenta muitos elementos:
npm query ':vuln([severity=high])'
Uma observação importante: a filtragem por gravidade corresponde exatamente a essa gravidade e a nada acima ou abaixo dela. [gravidade=alta] não exibirá resultados críticos. Passe-os como uma lista se quiser ambos:
npm query ':vuln([severity=critical],[severity=high])'
Os seletores permitem compor, de modo que você pode restringir a verificação à sua árvore de produção, em vez de recorrer a um sinalizador:
npm query '.prod#tslib:vuln' # este pacote, apenas na árvore de produção npm query '.prod:vuln' # tudo o que está vulnerável na árvore de produção
Mais duas coisas que você precisa saber antes de confiar nisso em um processo automatizado. :vuln e :outdated acessam o registro, portanto, nenhum dos dois funciona offline. E o formato #name@version , que você ainda encontra em documentações mais antigas, não é mais analisado – o npm 12 rejeita #[email protected] com um EQUERYNODEPTYPE . Use o pseudo-seletor semver em vez disso:
npm query '#tslib:semver(2.4.0)'
A seletor :vuln foi introduzido no npm 10.5.0. Se você não tiver certeza de qual versão está usando, verifique em vez de adivinhar:
npm query ':vuln' >/dev/null 2>&1 && echo "suportado" || echo "atualize o npm"
Para versões mais antigas, pule para o jq .
2. Filtrar npm audit JSON com jq
npm audit remonta à versão 6 do npm, enquanto :vuln requer o npm 10.5.0 ou posterior. Isso torna o JSON de auditoria a opção mais segura para um repositório compartilhado, onde os colaboradores podem estar usando versões mais antigas do npm.
npm audit --json | jq '.vulnerabilities["tslib"]'
O –json retorna dados de auditoria legíveis por máquina, em vez de uma tabela formatada. No npm 7 e versões posteriores, esse relatório contém uma chave de objeto “vulnerabilities” com chave no nome do pacote; assim, o filtro acima extrai a entrada para tslib diretamente. Obtenha os campos que realmente orientam uma decisão:
npm audit --json | jq '.vulnerabilities["tslib"] | {severity, range, fixAvailable}'
Read the top-level range as the aggregate vulnerable range for that entry. Do not reach into .via[0].range to get it. The via array mixes advisory objects with bare package-name strings for vulnerabilities inherited through a parent, and even when via[0] happens to be an object it often carries a narrower range than the entry as a whole – on a test tree, express reported <4.20.0 from via[0] against an aggregate range of <=4.21.2 || 5.0.0-alpha.1 – 5.0.0. Silently wrong is worse than empty.
Quando você quiser separar os avisos diretos dos herdados, solicite via explicitamente e leia você mesmo:
npm audit --json | jq '.vulnerabilities["tslib"] | {severity, range, via, fixAvailable}'
Use a sintaxe entre colchetes em vez de .vulnerabilities.tslib. São apenas dois caracteres a mais, e é a única forma que funciona com nomes de pacotes com escopo, enquanto a notação com ponto falha no @ e o /:
npm audit --json | jq '.vulnerabilities["@babel/traverse"]'
Para ver tudo o que foi sinalizado antes de analisar pacote por pacote:
npm audit --json | jq -r '.vulnerabilities | keys[]'
null Não significa que não haja vulnerabilidade
Se o filtro retornar null, tudo o que você descobriu é que o relatório não possui nenhuma entrada sob essa chave. Quatro situações diferentes geram esse mesmo null:
- A versão instalada não apresenta nenhum aviso nos dados consultados pelo npm.
- O pacote não faz parte da árvore auditada.
- O pacote foi excluído da auditoria, por exemplo, por meio de –omit=dev.
- O nome do pacote foi digitado incorretamente.
Faça com que o resultado diga algo, em vez de ficar adivinhando:
npm audit --json | jq '.vulnerabilities["tslib"] // "nenhuma entrada no relatório de auditoria"'
Em seguida, confirme se o pacote está realmente instalado, seguindo as instruções da seção 4.
Se você estiver restringindo o acesso a uma compilação com base nisso
O código de saída pode induzir você ao erro. O `npm audit retorna 1 sempre que encontra qualquer vulnerabilidade igual ou superior ao nível de auditoria configurado, em qualquer lugar da árvore – isso não diz nada sobre o pacote sobre o qual você perguntou. Aumentar o limite com –audit-level=high altera o momento em que o comando falha; isso não remove as descobertas de gravidade menor do relatório, que permanece idêntico em ambos os casos.
npm query funciona melhor aqui: ele retorna 0 independentemente de encontrar algo ou não, então você pode filtrar com base no próprio conjunto de resultados.
se [ "$(npm query '#tslib:vuln' | jq length)" -gt 0 ]; então echo "tslib vulnerável presente" fi
Se você se importa apenas com o que é enviado para produção, execute npm audit –omit=dev para o caminho de auditoria, ou use o .prod mostrado na seção 1 para o caminho de consulta. Uma falha crítica em uma dependência exclusiva da compilação é um caso diferente daquela encontrada na sua árvore de tempo de execução.
3. Pesquise rapidamente resultados legíveis por humanos com grep
Quando você quiser apenas uma visualização rápida e não quiser se preocupar com JSON, redirecione a saída padrão para grep.
npm audit | grep -A 5 -i "tslib"
O | operador entrega a saída padrão dopara o grep, que a analisa linha por linha. -A 5 imprime cinco linhas do contexto posterior a cada correspondência, o que pode capturar os detalhes do aviso ao redor. -i torna a correspondência insensível a maiúsculas e minúsculas.
Isso é delicado, e vale a pena explicar especificamente o motivo. O quebra-linha automático, mudanças no layout entre versões do npm e blocos de avisos mais longos do que a janela de contexto podem ocultar a parte de que você precisava. Pior ainda, uma falta de correspondência silenciosa é ambígua exatamente da mesma forma que “null” – pode significar que está tudo correto ou que seu padrão não detectou uma linha que sofreu quebra automática.
É bom para uma avaliação visual. Nunca use isso como prova de que um pacote não apresenta nenhuma vulnerabilidade conhecida.
4. Confirme quais versões estão realmente instaladas
Um relatório de auditoria descreve a árvore de dependências que o npm resolve a partir do seu arquivo de bloqueio. Por padrão o `npm audit` exige um package-lock.json ou `shrinkwrap`, envia os nomes e versões dos pacotes resolvidos para o registro e os compara com alertas conhecidos. Ele funciona até mesmo com –package-lock-only e sem diretório node_modules .
npm ls inspeciona a árvore de módulos instalados em node_modules: npm ls tslib
O filtro posicional aqui faz mais do que as pessoas esperam. O npm percorre toda a árvore e exibe o caminho de cada instância correspondente, incluindo cópias aninhadas — portanto, um pacote em quarto nível ainda aparece. Ao adicionar –all não altera essa saída quando você está filtrando por nome (verificado no npm 10 e no npm 12); –all é o que você quer para um npm lssem filtragem, em que a exibição padrão se limita às dependências diretas.
É provável que haja duplicatas. Um único projeto pode facilmente conter três cópias do mesmo pacote em versões diferentes, e apenas algumas delas se enquadram no intervalo vulnerável.
Não crie scripts que vão contra o npm ls Código de saída
npm ls tslib retorna 0 quando encontra uma correspondência e 1 quando não encontra, o que parece ser uma verificação de presença simples. Mas não é bem assim. Se o pacote correspondente estiver marcado como inválido, supérfluo ou ausente, o npm gera ELSPROBLEMS e retorna 1, embora ainda exiba o pacote encontrado. Uma dependência instalada, mas incompatível, é exibida como “não instalada”:
`– [email protected] inválido: “0.0.8” do projeto raiz
Código de erro do npm: ELSPROBLEMS
Problemas não relacionados em outras partes da árvore não contaminaram o código de saída filtrado durante os testes; portanto, isso é mais restrito do que parece — mas é exatamente o caso com o qual você provavelmente se deparará ao investigar uma incompatibilidade de versão. Para scripts, conte as correspondências com npm query , que retorna 0 independentemente do estado da árvore e também encontra cópias aninhadas:
[ "$(npm query '#tslib' | jq length)" -gt 0 ] && echo "instalado" || echo "não instalado"
Acessando npm ls –json para .dependencies[“tslib”] é uma alternativa tentadora e uma armadilha: os pacotes transitivos estão aninhados sob seus pais, de modo que uma consulta no nível superior indica que um pacote está ausente quando, na verdade, ele está dois níveis abaixo.
Mais uma coisa: o arquivo de bloqueio e node_modules ficam desincronizados constantemente. Depois de baixar as alterações, execute npm ci antes de considerar a árvore local como definitiva.
Bônus: Descubra por que o pacote está instalado
Quando o pacote sinalizado não estiver no seu próprio package.json, é porque outro elemento o inseriu lá. Execute este comando na raiz do projeto:
npm explain tslib
npm explain exibe a cadeia de dependências para cada instalação correspondente, de modo que cada cópia tenha seu próprio rastreamento até o projeto raiz. Quando houver várias cópias e você estiver interessado apenas em uma delas, passe o caminho dessa cópia:
npm explain node_modules/algum-pacote/node_modules/tslib
Isso exibe a cadeia dessa instância específica, incluindo os casos em que dois pais diferentes dependem do mesmo pacote intermediário.
Se for uma dependência direta sua → atualize-a você mesmo. Se um componente pai a tiver fixada → atualize o componente pai ou adicione um entrada de no package.json (npm 8.3+) como uma solução provisória. Uma substituição força uma versão com a qual o pacote pai nunca foi testado; portanto, trate-a como uma alteração que precisa ser respaldada por seu conjunto de testes, e não como uma correção de uma única linha.
O que O npm audit não pode lhe dizer
Considere tudo isso como uma triagem básica, e não como um programa de segurança de aplicativos. Nenhum desses comandos irá:
- Verifique se o seu aplicativo pode chegar ao caminho de código vulnerável.
- Analise a lógica do seu próprio código-fonte.
- Analisar de forma detalhada os binários nativos incluídos em um pacote.
- Detectar um pacote malicioso ou deliberadamente ofuscado antes que alguém o denuncie.
O primeiro ponto é o mais importante: o número de resultados da auditoria não corresponde ao número de vulnerabilidades exploráveis em seu aplicativo. E cada resultado depende da árvore que o npm resolveu, do registro no qual você está configurado e dos dados de alertas que existiam no momento em que você executou o comando. Execute a mesma auditoria na próxima semana e você poderá obter um resultado diferente, mesmo sem nenhuma alteração no seu código.
Considerações finais
A versão resumida, na ordem em que você deve testar:
npm query '#tslib:vuln' # verificação mais simples nativa do npm npm audit --json | jq '.vulnerabilities["tslib"]' # portátil, compatível com scripts npm ls tslib # o que está realmente instalado npm explain tslib # por que está instalado Uma verificação única no terminal é apenas um instantâneo, e o valor da análise de dependências vem da repetição. Ferramentas de monitoramento contínuo — como o Dependabot, um verificador de código aberto semelhante ao OSV-Scanner ou uma plataforma comercial de Análise de Composição de Software — irão identificar alertas recém-divulgados relativos a códigos que você ainda não alterou, manter as descobertas visíveis em todos os repositórios e automatizar parte do trabalho de atualização. O que elas não fazem é superar os limites mencionados acima: elas ainda operam principalmente com base em informações sobre vulnerabilidades conhecidas, e um pacote malicioso não relatado também fica invisível para elas.
Para preencher essa lacuna específica, é preciso antecipar a verificação em relação ao aviso, e essa é a abordagem adotada pelo TuxCare SecureChain para OSS — ele fornece suas dependências do npm a partir de um registro selecionado, no qual os pacotes são recompilados a partir do código-fonte e analisados antes mesmo de chegarem ao seu node_modules.
Os comandos do terminal continuam sendo úteis de qualquer maneira. Quando você precisa de uma resposta imediata sobre um pacote em um projeto, eles são mais rápidos do que abrir um painel.

