Cooldowns with SBOMs
Ritesh Noronha

In September 2025, an attacker phished a maintainer known as "qix" and pushed malicious updates to chalk, debug, and ansi-styles — packages with over 2.1 billion weekly downloads between them. The malicious versions were live on npm for roughly two hours before the community detected them and they were removed.
Two hours. If your CI pipeline ran during that window and your lockfile was open to the latest patch, you shipped malware.
This is the pattern. It repeats every few weeks now:
Nx (August 2025) — malicious packages live for 4–5 hours, SSH keys and GitHub tokens exfiltrated before takedown
Shai-Hulud worm (Sept–Nov 2025) — self-replicating npm worm spread across 25,000+ repositories before containment
LiteLLM (March 2026) — malicious PyPI releases using a
.pthfile for auto-execution and credential harvesting, yanked within hoursAxios (March 31, 2026) — malicious versions of a package with over 100M weekly downloads, connecting to a C2 operated by Sapphire Sleet
ua-parser-js, event-stream, colors, faker — the historical roll-call of compromises that every supply-chain talk cites
In every case, the malicious version lived in the registry for hours, not days. And in every case, anyone who simply waited before pulling the new version would have been fine.
That is the cooldown idea, and it is not new. What is new is that package managers have finally — belatedly, unevenly — started shipping cooldown features natively. And it's now clear the package-manager layer alone is not enough. This is where SBOMs come in.
The Package-Manager Cooldown Landscape (as of April 2026)
Between September 2025 and February 2026, seven major package managers shipped dependency-cooldown features:
Package Manager | Flag / Setting | Version |
|---|---|---|
pnpm |
| 10.16+ |
Yarn |
| 4.10.0 |
Bun |
| 1.3 |
Deno |
| 2.6 |
uv |
| 0.9.17 |
pip |
| 26.0 |
npm |
| 11.10.0 |
This is real progress. It is also wildly fragmented. Each ecosystem has its own flag, its own default (usually none), its own semantics for what "age" means. Organizations with polyglot stacks — and most modern organizations are polyglot — now have to configure cooldowns in seven different places, in seven different CI systems, and hope no team forgets.
More importantly, the package-manager cooldown is enforced at install time, on the developer's laptop or on a CI runner. That means:
It is opt-in per repo. One misconfigured
package.jsonand you're exposed.It doesn't apply to artifacts you already built. If a container image from last week pulled a malicious dependency, the package-manager cooldown cannot retroactively warn you.
It can be silently overridden — a
--no-cooldownflag, an.npmrcoverride committed by a well-meaning engineer, a CI cache that skips the check.It doesn't help with third-party software you didn't build — vendor deliverables, container base images, firmware.
There is no central audit trail. A security team cannot ask "which of our 400 services allowed a sub-48-hour dependency last quarter?" and get an answer.
This is a governance gap, not a tooling gap. And governance gaps are what SBOMs are for.
SBOMs as an Enforcement Layer
An SBOM is a post-build, ecosystem-agnostic inventory of what you actually shipped. That is a uniquely useful vantage point for cooldown enforcement:
Polyglot by default. A single SBOM policy can evaluate components across npm, PyPI, Maven, Go, Cargo, NuGet, OCI images, and embedded firmware — with one rule, not seven configs.
Post-build, not pre-install. You evaluate against what actually landed in the artifact, not what was intended by
package.json. No more "the lockfile said one thing, the build did another."Central, auditable, enforceable. Policies live in one place. Violations produce records. Violations are visible to security, compliance, and engineering simultaneously.
Shift-left and shift-right. The same rule can run in CI to block a release, and against existing production artifacts to find components that became risky after deployment.
Covers software you didn't compile. Vendor deliverables and base images ship with SBOMs now (CRA, FDA, EO 14028 all point in this direction). A package-manager cooldown cannot inspect them. A SBOM-layer cooldown can.
The package manager is where you prefer cooldowns to run — it's cheapest there. The SBOM is where you prove cooldowns ran — it's authoritative there. Both layers are useful. Only one is sufficient.
Introducing COMPONENT_PUBLISHED_AGE
Interlynk's platform now ships a policy subject called COMPONENT_PUBLISHED_AGE. It expresses exactly one idea: "for every component in an SBOM, look up when that specific version was published to its package registry, and compare that date to a policy threshold."
Three operators are supported:
Operator | Meaning | Example |
|---|---|---|
| Component was published within the last N days. Violates. |
|
| Component is older than N days. Violates. |
|
| Component falls inside a |
|
The boundary is exclusive — LESS_THAN 7 does not fire on a component published exactly 7 days ago. This matches every other age-based subject in the platform (vulnerability status age, assignment age, etc.) so there are no surprises.
LESS_THAN is the cooldown primitive. MORE_THAN is the inverse — staleness detection, for when a component has been abandoned and the ecosystem has moved on. RANGE is the two-sided version, useful for defining a "green zone" (e.g. "dependencies should be at least 14 days old but no older than 18 months").
When the policy runs, any component whose package_version.published_at falls inside the forbidden window produces a PolicyRuleViolation scoped to that specific component, with:
The component's PURL and version
The exact publication timestamp
The rule that matched
The SBOM (and therefore the project, release, and artifact) it appeared in
Violations flow through the same reporting, ticketing, and webhook pipeline as every other policy outcome — so a cooldown miss can automatically open a Jira ticket, gate a GitHub PR merge, or page the security team.
Where Cooldowns Would Have Helped — A Timeline
Here is the "what if we had a 48-hour cooldown?" counterfactual, applied to recent attacks:
Attack | Published → Yanked | Outcome with a 48-hour cooldown |
|---|---|---|
Nx (Aug 2025) | ~4–5 hours | Not adopted |
chalk / debug / ansi-styles (Sep 8) | ~2 hours | Not adopted |
Shai-Hulud worm (Sep–Nov 2025) | ~hours per version | Massively reduced blast radius |
LiteLLM (March 2026) | Hours | Not adopted |
Axios (Mar 31, 2026) | Hours | Not adopted |
event-stream (historical) | Days | Still adopted — cooldown alone insufficient |
ua-parser-js (historical) | ~12 hours | Not adopted |
The honest caveat: a cooldown is not a silver bullet. The event-stream attack persisted for months before anyone noticed — waiting 48 hours would not have helped. Cooldowns defend against the fast-burn class of supply chain attacks, which happens to be the majority of them today. They do not defend against long-running stealth compromises, maintainer takeover with patient staging, or build-system attacks like the Trivy tag-hijack. Those need other controls.
But if cooldowns catch even 70% of the in-the-wild attack patterns at effectively zero operational cost — which is what the recent incident data suggests — that is an enormous ROI for one policy rule.
Why "Shift Left with SBOM" Is the Right Architecture
There is a legitimate critique of cooldowns, most clearly articulated by Cal Paterson: they work by free-riding on the pain of less-protected users. If everyone waits 48 hours, no one detects the malicious package, because no one runs it. The detection is done by the early-adopters who get burned.
The proposed systemic fix is an upload queue at the registry — publication happens, but distribution is delayed while scanners run. Debian has done this for decades. npm, PyPI, and friends do not. Until they do, individual organizations have to defend themselves.
SBOM-layer cooldowns are a better individual defense than package-manager cooldowns for the same reasons outlined above: uniform, auditable, polyglot, covers third-party artifacts. And because SBOMs are generated as part of the build, before the artifact is released, the enforcement point is as far left as it can be without coupling to any specific package manager.
CI builds the artifact. Code is compiled, dependencies are resolved, container images are assembled.
SBOM is generated from the build output (CycloneDX or SPDX).
SBOM is uploaded to Interlynk, where the
COMPONENT_PUBLISHED_AGEpolicy runs alongside every other policy (license, vulnerability, supplier, lifecycle).Violations block the release. The PR is gated, the tag is held, the container is quarantined.
A full audit record exists — who built what, when, with which dependencies, and which policies passed or failed.
Crucially, the same policy also runs continuously on already-shipped SBOMs. If a new vulnerability is disclosed against a component you shipped, or (for our purposes) a component you shipped turns out to have been yanked from the registry post-facto, you learn about it without needing to re-run the build.

An Infographic to Put on the Wall
The clearest way to frame this internally is a two-axis picture:
Horizontal axis: time — from "published 1 hour ago" on the left to "published 5 years ago" on the right.
Vertical axis: risk — malicious-release risk on the left (decays over days), abandoned-project risk on the right (grows over years).
Plot the two curves. They cross somewhere around the 14–30 day mark. That crossing region is the green zone — components that are old enough to have survived post-publication scrutiny, but new enough that the project is still alive.
Then overlay the policy:
LESS_THAN 14— "you are in the red-curve danger zone, cool off"MORE_THAN 540— "you are in the blue-curve staleness zone, upgrade or retire"RANGE {min: 14, max: 540}— the exact green zone, expressed as one rule
That single picture is the entire argument. When you show it to engineering leadership, they stop asking why the security team wants another policy.

Getting Started — Free
COMPONENT_PUBLISHED_AGE is available on Interlynk's Community (free) tier. You can:
Sign up at interlynk.io — no credit card.
Generate an API key from your organization settings.
Upload an SBOM for any project (CycloneDX or SPDX JSON, any ecosystem).
Create a policy with subject
COMPONENT_PUBLISHED_AGE, operatorLESS_THAN, value7— call it "7-day cooldown."Run the policy and see exactly which components in your existing SBOMs would have been caught.
No per-seat fees, no per-SBOM metering on the Community tier. This is exactly the policy that should not have a paywall, so it doesn't.
What We're Not Claiming
A short list of honest limits:
Cooldowns do not replace SCA. Vulnerability scanning, license policy, supplier attestation, and lifecycle (abandoned/EOL) detection are all separate — and all still necessary.
Cooldowns do not replace pinning. You still want lockfiles, integrity hashes, and (ideally) signed artifacts. Cooldowns buy you time; pinning buys you certainty. Use both.
Cooldowns are statistical, not deterministic. A sophisticated attacker who stages their compromise over weeks will defeat a 48-hour window. Cooldowns raise the cost; they don't close the door.
The One-Line Summary
Package managers are finally shipping cooldowns, but fragmented, opt-in, per-ecosystem. SBOMs are the only place where cooldown policy can be uniform, auditable, and enforced across everything you ship — including software you didn't build.
If your organization already generates SBOMs, turn on COMPONENT_PUBLISHED_AGE LESS_THAN 7 today. It costs nothing, it catches the most common class of attack currently in the wild, and it gives you a defensible answer the next time a regulator asks what you do about supply-chain freshness.
If you don't generate SBOMs yet, this is one more reason to start.
References
Cooldown advocacy and analysis
Simon Willison — Package managers need to cool down
Christian Schneider — Dependency Cooldowns: Supply Chain Defense
Endor Labs — Why Cooldown Windows Belong in Every npm Security Strategy
Cal Paterson — Dependency cooldowns are free-riding
Recent incidents
Palo Alto Unit 42 — Shai-Hulud Worm Compromises npm Ecosystem
CISA — Widespread Supply Chain Compromise Impacting npm Ecosystem (Sept 2025)
Microsoft Security — Mitigating the Axios npm Supply Chain Compromise (April 2026)
Microsoft Security — Shai-Hulud 2.0: Detection and Defense Guidance
Upwind — Massive Compromise of debug, chalk, and 16 Other Packages
Interlynk
Sign up (free tier): interlynk.io
Open-source SBOM tooling: github.com/interlynk-io