Has instalado un paquete a través de npm, el el resultado de la auditoría de npm parecía correcto, y seguiste adelante.
Avancemos seis meses. Descargas los últimos cambios, algo falla en la integración continua y ahora necesitas una respuesta clara sobre una dependencia: ¿es tslib supone realmente un problema en este árbol? Revisar todo el informe de auditoría en busca de esa única respuesta es una tarea tediosa.
La versión actual de npm puede responder a esta pregunta de forma más directa. Puedes consultar el árbol de dependencias con un selector de vulnerabilidades y filtrar los datos estructurados de auditoría con jq, o recurrir a herramientas básicas de terminal cuando solo necesites un vistazo rápido. Así podrás averiguar exactamente por qué se ha instalado el paquete.
A continuación te presentamos cuatro formas de comprobar un único paquete de npm, en el orden en que deberías ir probándolas.
Nota: los comandos que aparecen a continuación se han probado con npm 10.9.7 y npm 12.0.1. Los selectores y los formatos de salida varían entre las distintas versiones principales de npm, así que ejecuta npm -v antes de integrar nada de esto en un script.
1. Consultar el paquete directamente con npm query
npm query recorre el árbol de dependencias instaladas utilizando selectores de dependencias al estilo CSS. En este caso, dos de ellos se encargan de la tarea: #tslib coincide con paquetes llamados tslib, y :vuln limita los resultados a las instancias con un aviso conocido.
npm query '#tslib:vuln'
Una matriz vacía significa que npm no ha encontrado ninguna instancia de ese paquete que coincida con un aviso conocido en los datos del árbol y del registro que ha consultado. Una matriz con entradas significa que sí la ha encontrado, y cada entrada contiene metadatos detallados sobre el paquete y el árbol de dependencias, además de una campo de ubicación que indica dónde se encuentra esa copia dentro de node_modules.
Esa descarga de metadatos es una gran cantidad de JSON para una sola pregunta. Recórtala con jq:
npm query '#tslib:vuln' | jq '.[] | {location, version, advisories: [.queryContext.advisories[] | {severity, title}]}'
La selector :vuln asigna cada aviso que coincida al nodo situado bajo queryContext.advisories, de modo que obtienes la gravedad, el título, la puntuación CVSS, el CWE y el rango de versiones vulnerables sin necesidad de un segundo comando; además, obtienes todos ellos, no solo el primero.
Puedes filtrar por gravedad dentro del selector, lo que resulta útil cuando el árbol contiene mucha información irrelevante:
npm query ':vuln([severity=high])'
Una cosa a tener en cuenta: el filtrado por gravedad solo muestra los casos con esa gravedad exacta, ni los que estén por encima ni por debajo. [gravedad=alta] no te mostrará los hallazgos críticos. Pásalos como una lista si quieres ambos:
npm query ':vuln([severity=critical],[severity=high])'
Los selectores permiten estructurar el código, por lo que puedes limitar la comprobación a tu árbol de producción en lugar de tener que recurrir a un indicador:
npm query '.prod#tslib:vuln' # este paquete, solo en el árbol de producción npm query '.prod:vuln' # todo lo vulnerable en el árbol de producción
Hay dos cosas más que debes saber antes de confiar en esto en la automatización. :vuln y :outdated acuden al registro, por lo que ninguno de los dos funciona sin conexión. Y el #name@version , que todavía aparece en documentación más antigua, ya no se analiza: npm 12 rechaza #[email protected] con un EQUERYNODEPTYPE . Utiliza en su lugar el pseudo-selector semver:
npm query '#tslib:semver(2.4.0)'
La selector :vuln se incorporó en la versión 10.5.0 de npm. Si no estás seguro de qué versión estás utilizando, compruébalo en lugar de darlo por sentado:
npm query ':vuln' >/dev/null 2>&1 && echo "compatible" || echo "actualizar npm"
Si tu versión es anterior, ve directamente a la sección jq .
2. Filtrar npm audit JSON con jq
npm audit se remonta a npm 6, mientras que :vuln requiere npm 10.5.0 o posterior. Por eso, el JSON de «audit» es la opción más segura para un repositorio compartido en el que los colaboradores puedan estar utilizando versiones anteriores de npm.
npm audit --json | jq '.vulnerabilities["tslib"]'
El opción –json devuelve datos de auditoría legibles por máquina en lugar de una tabla formateada. En npm 7 y versiones posteriores, ese informe contiene una objeto «vulnerabilities» con el nombre del paquete como clave, por lo que el filtro anterior extrae la entrada correspondiente a tslib directamente. Obtén los campos que realmente influyen en la decisión:
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.
Cuando quieras diferenciar los avisos directos de los heredados, solicita por de forma explícita y léelo tú mismo:
npm audit --json | jq '.vulnerabilities["tslib"] | {severity, range, via, fixAvailable}'
Utiliza la sintaxis entre corchetes en lugar de .vulnerabilities.tslib. Solo supone dos caracteres más y es la única forma que se mantiene intacta con un nombre de paquete con ámbito, mientras que la notación con punto falla en el @ y el /:
npm audit --json | jq '.vulnerabilities["@babel/traverse"]'
Para ver todo lo marcado antes de ir paquete por paquete:
npm audit --json | jq -r '.vulnerabilities | keys[]'
null No significa que no haya vulnerabilidades
Si el filtro devuelve null, lo único que has averiguado es que el informe no tiene ninguna entrada con esa clave. Hay cuatro situaciones diferentes que dan lugar a ese mismo null:
- La versión instalada no presenta ninguna advertencia en los datos consultados por npm.
- El paquete no forma parte del árbol auditado.
- El paquete se excluyó de la auditoría, por ejemplo, mediante –omit=dev.
- El nombre del paquete se ha introducido de forma incorrecta.
Haz que el resultado diga algo en lugar de tener que adivinarlo:
npm audit --json | jq '.vulnerabilities["tslib"] // "no hay ninguna entrada en el informe de auditoría"'
A continuación, comprueba que el paquete esté realmente instalado siguiendo los pasos indicados en la sección 4.
Si estás restringiendo el acceso a una compilación en este caso
El código de salida te llevará a error. npm audit devuelve el código 1 cada vez que encuentra alguna vulnerabilidad igual o superior al nivel de auditoría configurado, en cualquier parte del árbol; eso no dice nada sobre el paquete por el que has preguntado. Si aumentas el umbral con –audit-level=high cambia el momento en que el comando falla; no elimina del informe los hallazgos de menor gravedad, por lo que este sigue siendo idéntico en ambos casos.
npm query funciona mejor aquí: devuelve un valor de salida 0 tanto si encuentra algo como si no, por lo que puedes basar la decisión en el propio conjunto de resultados.
si [ "$(npm query '#tslib:vuln' | jq length)" -gt 0 ]; entonces echo "se ha detectado una versión vulnerable de tslib" fi
Si solo te interesa lo que se envía a producción, ejecuta npm audit –omit=dev para la ruta de auditoría, o utiliza el .prod que se muestra en la sección 1 para la ruta de consulta. Un hallazgo crítico en una dependencia exclusiva de la compilación es un tema distinto al de uno que se encuentre en tu árbol de tiempo de ejecución.
3. Busca rápidamente en resultados legibles para el ser humano con grep
Cuando solo quieras echar un vistazo rápido y no quieras complicarte con JSON, redirige la salida estándar a grep.
npm audit | grep -A 5 -i "tslib"
El | El operador entrega la salida estándar dea grep, que la analiza línea por línea. -A 5 imprime cinco líneas de contexto posterior a cada coincidencia, lo que puede capturar los detalles de las advertencias circundantes. -i hace que la búsqueda no distinga entre mayúsculas y minúsculas.
Esto es delicado, y conviene explicar con detalle por qué. Los saltos de línea, los cambios de maquetación entre versiones de npm y los bloques de avisos más largos que la ventana de contexto pueden ocultar la parte que necesitabas. Peor aún, una falta de coincidencia silenciosa es ambigua precisamente de la misma forma que «null» : puede significar que no hay nada, o que tu patrón se ha saltado una línea que se ha ajustado.
Vale para una evaluación a ojo. Nunca lo utilices como prueba de que un paquete no tiene ninguna vulnerabilidad conocida.
4. Comprueba qué versiones están realmente instaladas
Un informe de auditoría describe el árbol de dependencias que npm resuelve a partir de tu archivo de bloqueo. Por defecto npm audit requiere un package-lock.json o shrinkwrap, envía los nombres y versiones de los paquetes resueltos al registro y los compara con los avisos conocidos. Incluso se ejecutará con –package-lock-only y sin directorio node_modules .
npm ls inspecciona el árbol de módulos instalado en node_modules: npm ls tslib
El filtro posicional hace aquí más de lo que la gente espera. npm recorre todo el árbol y muestra la ruta de cada instancia que coincide, incluidas las copias anidadas, por lo que un paquete situado a cuatro niveles de profundidad sigue apareciendo. Al añadir –all no modifica ese resultado cuando se filtra por nombre (verificado en npm 10 y npm 12); –all es lo que necesitas para un npm lssin filtrar, en el que la vista predeterminada se limita a las dependencias directas.
Es probable que haya duplicados. Un mismo proyecto puede contener fácilmente tres copias del mismo paquete en diferentes versiones, y solo algunas de ellas se encuentran dentro del rango vulnerable.
No escribas scripts que vayan en contra de npm ls Código de salida
npm ls tslib devuelve 0 cuando encuentra una coincidencia y 1 cuando no la encuentra, lo que parece una comprobación de presencia sencilla. Pero no es exactamente así. Si el paquete con el que coincide está marcado como inválido, superfluo o ausente, npm genera ELSPROBLEMS y sale con el código de salida 1, aunque sigue mostrando el paquete que ha encontrado. Una dependencia instalada pero que no coincide aparece como «no instalada»:
`– [email protected] no válido: «0.0.8» del proyecto raíz
Código de error de npm: ELSPROBLEMS
Los problemas ajenos a esta parte del árbol no afectaron al código de salida filtrado durante las pruebas, por lo que se trata de un caso más concreto de lo que parece; pero es precisamente el caso con el que probablemente te encontrarás al investigar una discrepancia de versiones. En el caso de los scripts, cuenta las coincidencias con npm query , que devuelve 0 independientemente del estado del árbol y también detecta copias anidadas:
[ "$(npm query '#tslib' | jq length)" -gt 0 ] && echo "instalado" || echo "no instalado"
Accediendo a npm ls –json para .dependencies[“tslib”] es una alternativa tentadora y, a la vez, una trampa: los paquetes transitivos se anidan bajo sus padres, por lo que una búsqueda en el nivel superior indica que un paquete no está presente cuando en realidad se encuentra dos niveles más abajo.
Una cosa más: el archivo de bloqueo y node_modules se desincronizan constantemente. Después de descargar los cambios, ejecuta npm ci antes de considerar que el árbol local es el de referencia.
Extra: Descubre por qué se instala el paquete
Cuando el paquete marcado no se encuentre en tu propio package.json, es que algo más lo ha introducido allí. Ejecuta esto desde el directorio raíz del proyecto:
npm explain tslib
npm explain muestra la cadena de dependencias de cada instalación que coincida, de modo que cada copia tiene su propio rastro hasta el proyecto raíz. Cuando existan varias copias y solo te interese una, indica su ruta:
npm explain node_modules/some-package/node_modules/tslib
Esto muestra la cadena de esa instancia concreta, incluidos los casos en los que dos paquetes padres diferentes dependen ambos del mismo paquete intermedio.
Si se trata de una dependencia directa tuya → actualízala tú mismo. Si la ha fijado un componente padre → actualiza el componente padre o añade un entrada de en package.json (npm 8.3+) como solución provisional. Una anulación impone una versión con la que el paquete principal nunca se ha probado, así que trátala como un cambio que requiere tu conjunto de pruebas, no como una corrección de una sola línea.
¿Qué es npm audit no te puede decir
Considera todo esto como una evaluación inicial, más que como un programa de seguridad de aplicaciones. Ninguno de estos comandos:
- Averigua si tu aplicación puede llegar a la ruta de código vulnerable.
- Revisa la lógica de tu propio código fuente.
- Analizar de forma exhaustiva los binarios nativos incluidos en un paquete.
- Detectar un paquete malicioso o deliberadamente enmascarado antes de que alguien lo denuncie.
Lo primero es lo más importante: el número de resultados de la auditoría no equivale al número de vulnerabilidades explotables en tu aplicación. Además, cada resultado depende del árbol que npm haya resuelto, del registro con el que tengas configurado el sistema y de los datos de avisos que existieran en el momento en que ejecutaste el comando. Si realizas la misma auditoría la semana que viene, es posible que obtengas un resultado diferente sin que hayas modificado tu código.
Reflexiones finales
La versión resumida, para que lo pruebes:
npm query '#tslib:vuln' # comprobación nativa de npm más limpia npm audit --json | jq '.vulnerabilities["tslib"]' # portátil y compatible con scripts npm ls tslib # ¿Qué está instalado realmente? npm explain tslib # por qué está instalado Una comprobación puntual en la terminal es una instantánea, y el valor del análisis de dependencias reside en la repetición. Las herramientas de supervisión continua —como Dependabot, un escáner de código abierto como OSV-Scanner o una plataforma comercial de análisis de la composición del software— sacarán a la luz los avisos de seguridad recién publicados que afecten a código que no hayas modificado, mantendrán los resultados visibles en todos los repositorios y automatizarán parte del trabajo de actualización. Lo que no harán es superar los límites mencionados anteriormente: siguen basándose principalmente en información sobre vulnerabilidades conocidas, y un paquete malicioso no notificado también les resultará invisible.
Para subsanar esa vulnerabilidad concreta, hay que realizar la comprobación antes de que se publique el aviso, que es precisamente el enfoque que adopta TuxCare SecureChain para el software libre: te proporciona tus dependencias de npm desde un registro seleccionado cuidadosamente, en el que los paquetes se recompilan desde el código fuente y se analizan antes de que lleguen a tu node_modules.
Los comandos de la terminal siguen siendo útiles en cualquier caso. Cuando necesitas una respuesta inmediata sobre un paquete de un proyecto, son más rápidos que abrir un panel de control.

