Auditor de enfriamiento de dependencias
CLI open source que audita el enfriamiento de dependencias (min-release-age) de un proyecto JavaScript desde su lockfile, para npm, pnpm, Yarn y Bun, y da la configuración lista para pegar.
- Rol
- Diseño y desarrollo
- Año
- 2026
- Publicado
- 14 de septiembre de 2026
dep-cooldown es una herramienta de línea de comandos en TypeScript que audita el enfriamiento de dependencias (cooldown; npm lo llama min-release-age) de un proyecto JavaScript leyendo el lockfile que ya tienes: cuándo se publicó de verdad cada versión resuelta, cuántos días tenía, si trae procedencia y si está deprecada. Funciona con npm, pnpm, Yarn y Bun, e imprime el bloque de configuración para activar el enfriamiento en los cuatro. No instala nada: lee el lockfile, no node_modules.
Se ejecuta sin clonar ni instalar: npx dep-cooldown
Dos preguntas
Un enfriamiento le dice al gestor de paquetes que ignore las versiones publicadas hace menos de N días. Casi todas las campañas recientes contra npm se detectaron y retiraron en horas —las versiones maliciosas de debug y chalk estuvieron vivas dos horas—, así que un retraso modesto te saca de la ventana de exposición. Los cuatro gestores ya lo soportan de forma nativa; lo que quedaba por contestar era ¿me habría servido? y ¿cómo lo activo sin equivocarme de unidad?
Es la herramienta que acompaña al artículo «npm y la cadena de suministro: el gusano que se coló por el trusted publishing», donde el enfriamiento es la primera de las cuatro medidas.
Características
- Los cuatro formatos de lockfile:
package-lock.jsonynpm-shrinkwrap.json(v3, v2 y v1),pnpm-lock.yaml(v9, v6 y v5, incluido el documento de entorno que escribe pnpm 11+),yarn.lock(classic y Berry) ybun.lock. Detecta cuál hay —y avisa si encuentra varios—, separa dependencias directas de transitivas y consulta los alias por su nombre publicado. - Una tabla con lo que importa: fecha de publicación de cada versión (el
timedel registro), edad en días —en horas si no llega a uno—, directa o transitiva, procedencia (dist.attestations) y deprecación. Por defecto solo lista lo que pide atención;--alllo enseña todo y--jsonda la estructura completa. --as-of <fecha>rebobina el reloj: calcula las edades respecto al día que instalaste y no respecto a hoy, porque el día de la instalación es cuando el riesgo fue mayor. Si no la pasas, el informe sugiere la fecha de modificación de tu propio lockfile.--configimprime la configuración de npm, pnpm, Yarn, Bun o los cuatro, con la conversión de unidades hecha y la URL de la documentación oficial como comentario.- Pensado para CI: sale con
1si algo es más joven que el umbral, con2si hay un error de uso, con0si todo tiene la edad mínima y con3si nada es joven pero algo no se pudo comprobar —porque lo que no se comprobó no cuenta como aprobado—. Como nunca instala nada, en ese job no corre ningún script de ciclo de vida de terceros. - No se fía del lockfile a ciegas: comprueba que el
resolvedde cada entrada sea de verdad el tarball del registro para esa versión —npm ciinstala lo que diceresolved, no lo que diceversion— y lista como omitido lo que no tiene fecha de registro (git,file:, workspaces) en lugar de hacerlo desaparecer. - Respeta tu registro sin filtrar secretos: lee
registry=y@scope:registry=del.npmrccomo lo hace npm 11, nunca envía tokens y oculta en los informes las credenciales de la URL; consulta como máximo 8 paquetes a la vez, con tiempo y tamaño acotados, y guarda en caché 24 horas lo que necesita. - Probado y ligero: 245 pruebas sin red —con lockfiles reales de npm 11, pnpm 7, 9 y 12, Yarn 1 y 4 y Bun, y una revisión de seguridad cuyas reproducciones quedaron como pruebas—, CI en Node 20, 22 y 24 que instala el paquete empaquetado y lo ejecuta como lo haría un usuario, y una sola dependencia en tiempo de ejecución. Se aplica su propia medicina: su
.npmrcllevamin-release-age=7y el CI audita su propio lockfile.
La trampa de las unidades
Los cuatro gestores coinciden en la idea y discrepan en todo lo demás, empezando por la unidad: npm mide en días (min-release-age), pnpm en minutos (minimumReleaseAge), Yarn en minutos (npmMinimalAgeGate, que también acepta 7d) y Bun en segundos (minimumReleaseAge). Siete días son 7, 10080, 10080 y 604800: quien copia en Bun el valor de pnpm se queda con menos de tres horas de enfriamiento sin enterarse. --config all hace la cuenta.
Hay dos detalles más que las claves no dejan ver: la lista de exclusión de Yarn no se llama como su puerta de edad (es npmPreapprovedPackages, y exime de todas las puertas), y el enfriamiento se aplica al instalar, no al sugerir actualizaciones, así que el bot de dependencias abrirá el PR igual y el npm ci fallará después.
Lo que un enfriamiento no para
Un enfriamiento compra tiempo contra una publicación comprometida, y nada más. La herramienta lo dice en su propia documentación para que nadie la despliegue creyendo otra cosa:
- Un runner de CI comprometido. La oleada de Shai-Hulud contra TanStack de mayo de 2026 entró por el propio trusted publishing y generó una procedencia Sigstore auténtica. Por eso la columna de procedencia es información, no una nota de seguridad.
- Un script de instalación malicioso. El enfriamiento decide qué versión instalas, no qué pasa al instalarla: para eso está
npm ci --ignore-scripts. - Una campaña que dure más que tu umbral, ni lo que ya está fijado en tu lockfile.
Frente a lo que ya existe
Hay trabajo previo: pkg-age, pmsec, dos proyectos distintos llamados npm-cooldown, screen-node, supply-chain-guard, check-outdated --min-age y npm-check-updates --cooldown. Cada uno responde otra pregunta, de si una dependencia está abandonada a qué actualizaciones respetan un umbral. Lo nuevo de dep-cooldown es la combinación: auditoría del lockfile en los cuatro formatos, simulación retrospectiva con --as-of, procedencia y deprecación en la misma tabla, y configuración para los cuatro gestores. En la comparación del README, contrastada con el código publicado de cada una el 14 de septiembre de 2026, ninguna de las otras ocho simula contra una fecha arbitraria ni genera la configuración de los gestores, y solo screen-node mira la procedencia, y únicamente en las dependencias directas.
Stack técnico
- TypeScript estricto, compilado a ESM con tsup
- Node.js ≥ 20, con yaml como única dependencia (para
pnpm-lock.yaml) - Parsers propios para los lockfiles de npm, Yarn y Bun
- node:test para las pruebas, con el registro simulado desde fixtures
- GitHub Actions para el CI
- Licencia MIT; las piezas también se exportan como librería (
detectAndParse,buildAudit,createRegistryClient)
Repositorio
Ver en GitHub → · Paquete en npm →
Objetivo
Convertir en una comprobación la medida con mejor relación impacto/esfuerzo del artículo sobre la cadena de suministro de npm: saber, con el lockfile en la mano, qué habría frenado un enfriamiento el día que instalaste, y activarlo en cualquier gestor sin caer en la trampa de las unidades. Y dejar escrito, en la misma herramienta, lo que un enfriamiento no protege.