Open Source · Security Published

Dependency Cooldown Auditor

Open-source CLI that audits the dependency cooldown (min-release-age) of a JavaScript project from its lockfile, for npm, pnpm, Yarn and Bun, and prints ready-to-paste config.

Role
Design & Development
Year
2026
Published
September 14, 2026
Cover of dep-cooldown with a 7-day lockfile report flagging pnpm, vitest and rolldown as YOUNG and 109 packages under the threshold with exit 1, a 7-day cooldown seal and that same threshold in npm, pnpm, Yarn and Bun units on a dark background.

dep-cooldown is a TypeScript command-line tool that audits the dependency cooldown of a JavaScript project (npm calls it min-release-age) from the lockfile you already have: when every resolved version was actually published, how many days old it was, whether it carries provenance and whether it is deprecated. It works with npm, pnpm, Yarn and Bun, and prints the configuration block that turns the cooldown on in all four. It installs nothing: it reads the lockfile, not node_modules.

Nothing to clone or install: npx dep-cooldown

Two questions

A cooldown tells your package manager to ignore versions published less than N days ago. Almost every recent npm supply-chain campaign was detected and pulled within hours —the malicious debug and chalk versions were live for two hours— so a modest delay takes you out of the exposure window. All four managers support it natively now; what was left to answer was would it have helped? and how do I turn it on without getting the unit wrong?

It is the companion tool to npm Supply Chain: The Worm That Walked In Through Trusted Publishing, where the cooldown is the first of four measures.

Features

  • All four lockfile formats: package-lock.json and npm-shrinkwrap.json (v3, v2 and v1), pnpm-lock.yaml (v9, v6 and v5, including the environment document pnpm 11+ writes), yarn.lock (classic and Berry) and bun.lock. It detects which one is there —and warns when it finds several—, tells direct dependencies from transitive ones and looks aliases up under their published name.
  • One table with what matters: each version’s publish date (the registry’s time), age in days —in hours under a day—, direct or transitive, provenance (dist.attestations) and deprecation. By default it lists only what needs attention; --all shows everything and --json gives the whole structure.
  • --as-of <date> rewinds the clock: it measures ages against the day you installed rather than today, because install day is when the risk was highest. When omitted, the report suggests your lockfile’s own modification date.
  • --config prints the configuration for npm, pnpm, Yarn, Bun or all four, with the unit conversion done and the official documentation URL as a comment.
  • Built for CI: it exits 1 when anything is younger than the threshold, 2 on a usage error, 0 when everything is old enough and 3 when nothing is young but something could not be checked —because a check that did not run is not a pass—. Because it never installs anything, no third-party lifecycle script runs in that job.
  • Does not take the lockfile on faith: it checks that each entry’s resolved URL really is the registry tarball for that version —npm ci installs what resolved says, not what version says— and lists what has no registry date (git, file:, workspaces) as skipped instead of dropping it.
  • Honours your registry without leaking it: it reads registry= and @scope:registry= from .npmrc the way npm 11 does, never sends a token and hides URL credentials in its reports; it queries at most 8 packages at a time, with bounded time and size, and caches what it needs for 24 hours.
  • Tested and lean: 245 offline tests —with real lockfiles from npm 11, pnpm 7, 9 and 12, Yarn 1 and 4 and Bun, and a security review whose reproductions became tests—, CI on Node 20, 22 and 24 that installs the packed tarball and runs it the way a user would, and a single runtime dependency. It takes its own medicine: its .npmrc carries min-release-age=7 and CI audits its own lockfile.

The unit trap

The four managers agree on the idea and disagree on everything else, starting with the unit: npm measures in days (min-release-age), pnpm in minutes (minimumReleaseAge), Yarn in minutes (npmMinimalAgeGate, which also accepts 7d) and Bun in seconds (minimumReleaseAge). Seven days is 7, 10080, 10080 and 604800: copy pnpm’s value into Bun and you get a cooldown of under three hours without noticing. --config all does the arithmetic.

Two more details the key names hide: Yarn’s exclusion list is not named after its age gate (it is npmPreapprovedPackages, and it exempts a package from every gate), and the cooldown is enforced at install time, not at update-suggestion time, so your dependency bot will still open the PR and npm ci will fail afterwards.

What a cooldown does not stop

A cooldown buys time against a compromised publish, and nothing else. The tool says so in its own documentation, so nobody deploys it thinking otherwise:

  • A compromised build runner. The May 2026 Shai-Hulud wave against TanStack came in through trusted publishing itself and minted genuine Sigstore provenance. That is why the provenance column is information, not a safety rating.
  • A malicious install script. A cooldown decides which version you install, not what happens while installing it: that is what npm ci --ignore-scripts is for.
  • A campaign that outlives your threshold, or anything already pinned in your lockfile.

Against what already exists

There is prior work: pkg-age, pmsec, two different projects called npm-cooldown, screen-node, supply-chain-guard, check-outdated --min-age and npm-check-updates --cooldown. Each answers a different question, from whether a dependency is abandoned to which upgrades respect a threshold. What is new in dep-cooldown is the combination: a lockfile audit across all four formats, a retrospective --as-of simulation, provenance and deprecation in the same table, and config for all four managers. In the README’s comparison, checked against each tool’s published code on 14 September 2026, none of the other eight simulates against an arbitrary date or generates manager config, and only screen-node looks at provenance, for direct dependencies only.

Tech stack

  • TypeScript, strict, compiled to ESM with tsup
  • Node.js ≥ 20, with yaml as the only dependency (for pnpm-lock.yaml)
  • Hand-written parsers for the npm, Yarn and Bun lockfiles
  • node:test for the suite, with the registry mocked from fixtures
  • GitHub Actions for CI
  • MIT licence; the pieces are also exported as a library (detectAndParse, buildAudit, createRegistryClient)

Repository

View on GitHub → · Package on npm →

Goal

To turn the best impact-to-effort measure from the npm supply-chain article into a check: know, lockfile in hand, what a cooldown would have held back on the day you installed, and switch it on in any manager without falling into the unit trap. And to write down, in the tool itself, what a cooldown does not protect you from.

07 / Contact

Did any of this help? If your company needs it built, let's talk.

Fill out the form and I'll reply within 24 hours. You can also email me directly: