Dependabot Says Update Now. Supply-Chain Attacks Say Slow Down.
- Konrad Madej
- DevOps
- 18 Jul, 2026
- 07 Mins read
On September 8, 2025, someone phished the maintainer of chalk and debug, two of the most downloaded packages on npm. The malicious versions were live for about two hours before they were pulled. In those two hours, the code reached roughly one in ten cloud environments. The packages involved account for over two billion downloads a week.
Here’s the uncomfortable part. The teams that got hit were, by every standard we’ve taught for a decade, doing the right thing. They had automated dependency updates. They merged fast. Their bots picked up the new versions within minutes of publication. Being a diligent, fast updater is precisely what made them victims.
I’ve spent enough time around enterprise delivery teams to know how this lands. Security tells you to patch faster. Then security tells you the patch was the attack. Both statements are correct, and that’s the problem this article is about.
Two good practices now point in opposite directions
Let me define the conflict precisely, because I think most teams feel it without naming it.
The patch-fast clock. When a vulnerability gets a CVE, attackers move quickly. VulnCheck found that 32% of vulnerabilities exploited in the first half of 2025 were exploited on or before the day the CVE was published, up from 24% the year before. Google’s Mandiant team tracked average time-to-exploit falling from 63 days in 2018 to about 5 days in 2023. Every day you sit on a known vulnerability is measurable, growing risk. This is why Dependabot, Renovate, and every security scanner in your pipeline push you to update now.
The fresh-release clock. Malicious code enters ecosystems through newly published package versions: a maintainer gets phished, a CI pipeline gets poisoned, a token gets stolen, and version 4.1.2 of something you’ve trusted for years ships with a payload. The window of danger is the first hours and days after publication, before scanners and researchers catch it. The faster you adopt new versions, the more of that window you absorb.
Same clock, opposite advice. For known CVEs, waiting punishes you. For fresh releases, speed punishes you. A dependency policy that only optimizes one of these clocks is half a policy.
The attacks really do arrive through fresh releases
This isn’t a theoretical risk. The last two years produced a steady drumbeat, and the pattern is remarkably consistent.
The Shai-Hulud worm hit npm in September 2025. It compromised over 500 packages, starting from @ctrl/tinycolor with its two million weekly downloads. What made it a worm: it used stolen npm tokens to automatically publish trojanized versions of every other package the victim maintained. Read that again. The infection vector was the update itself. The worm’s propagation code literally queried the registry for packages owned by each compromised maintainer and force-published new versions of them.
CISA’s official advisory contained a sentence I’d frame and hang on the wall of every platform team: it recommended teams pin dependencies to versions published before September 16, 2025. The US government agency whose entire identity is “patch faster” told the industry to stop updating.
Two months later, Shai-Hulud 2.0 was worse: 796 packages backdoored across more than a thousand versions, together representing over 20 million weekly downloads, with credentials stolen from hundreds of GitHub users and over a hundred organizations. In May 2026 a similar worm hit the @tanstack, @uipath, and @mistralai namespaces, 373 malicious versions across 169 packages, this time extracting OIDC tokens directly from CI runner memory.
And my personal favourite for sheer cruelty: the ultralytics compromise in December 2024. The popular YOLO computer vision package shipped a malicious version. A fixed version followed. The fix was also malicious. People who updated immediately to remediate got compromised a second time for their diligence.
The window data makes the case for waiting
Here’s where it gets actionable. William Woodruff (maintainer of pip-audit and sigstore-python) compiled the detection windows for ten major supply-chain attacks: the time from malicious publish to public detection. The chalk compromise lasted under 12 hours. Solana’s web3.js backdoor, about 5 hours. The Nx compromise, 4 hours. The tj-actions GitHub Action attack, around 3 days.
Eight of the ten attacks had windows under one week.
The implication is almost embarrassingly simple. If you wait seven days before adopting a new package version, the ecosystem’s scanners, researchers, and unlucky early adopters will have caught the vast majority of malicious releases before they ever reach your build. Woodruff estimates an 80 to 90 percent reduction in exposure, essentially for free. Linux distributions have worked this way for decades: packages sit in unstable and testing before they reach stable. Instant-publish registries like npm and PyPI removed that gate, and we’re now retrofitting it.
The exception that defines the ceiling is xz-utils, the 2024 backdoor that took a two-and-a-half-year social engineering campaign and still went five weeks before detection. No reasonable cooldown catches that. Notably, though, the distro model worked even there: the backdoor was caught while still confined to testing and rolling releases, before it reached stable Debian or Ubuntu.
Why “just review the diff” doesn’t survive contact with reality
The standard objection is that teams should review dependency updates before merging. I don’t believe anyone who claims to do this at scale, and the numbers back me up.
Sonatype catalogued over 454,000 new malicious open source packages in 2025 alone. The Shai-Hulud payload was a 3.6 MB minified JavaScript bundle buried in a lifecycle hook. Nobody reads that in code review. Meanwhile the volume of legitimate updates makes careful review economically absurd: Endor Labs found that fewer than 9.5% of dependency vulnerabilities are actually reachable from your code, while about 95% of version upgrades contain at least one potentially breaking change. Your engineers learned long ago that most alerts are noise, which is why automated security PRs get merged at half the rate of human ones.
So the real-world choice is not “review everything” versus “auto-merge everything.” It’s whether your automation has a deliberate policy or an accidental one.
Cooldowns went from niche feature to industry default in about a year
The tooling landscape shifted faster than any I can remember. Renovate has had minimumReleaseAge for years, and hardly anyone used it. Then, in July 2025, GitHub shipped cooldown support in Dependabot: a cooldown block in dependabot.yml, with separate delays for major, minor, and patch updates. It arrived two and a half months before Shai-Hulud, when almost nobody had turned it on.
After Shai-Hulud, everyone caught up at once. pnpm added minimumReleaseAge and then turned it on by default, making it the first major package manager to ship with a cooldown out of the box. npm added a native min-release-age setting. pip 26.1 added --uploaded-prior-to, citing Woodruff’s data directly. Yarn, Bun, Deno, uv, Poetry, and Bundler all shipped equivalents. Andrew Nesbitt’s survey of cooldown support across package managers is the best current map of the landscape.
If your organization hasn’t made a decision about cooldowns yet, understand that your package manager may have already made one for you.
A cooldown alone is not a policy
Here’s where the two clocks come back. A blanket seven-day delay on everything is exactly wrong for the known-CVE case, where a third of exploited vulnerabilities are exploited on day zero. The resolution is to stop treating all updates as one category. Three lanes cover most of it:
The security lane. A release that fixes a known, exploited vulnerability (CISA’s KEV catalogue is the cleanest trigger) bypasses the cooldown. You take the small fresh-release risk because the known-CVE risk is larger and already being exploited. This is also the pip team’s own guidance: pair cooldowns with a scanner so critical fixes can jump the queue.
The routine lane. Everything else waits. Seven days as a floor, fourteen if your risk tolerance is low. Woodruff’s data says seven days clears the large majority of malicious versions; fourteen cleared everything in his dataset except xz-utils. Configure it once in Dependabot or Renovate and it costs you nothing day to day.
The watchlist lane. Dependencies with install scripts, CI actions, and anything that touches credentials deserve more than a delay. Pin GitHub Actions to commit SHAs, not tags. Disable lifecycle scripts by default where your package manager allows it (pnpm now refuses to run dependency postinstall scripts unless you allow-list them, which would have neutered Shai-Hulud’s first wave entirely). Check provenance attestations where they exist, with the caveat that adoption is still thin and the TanStack attack proved provenance verifies where a package was built, not that it’s benign.
Add one organizational rule: the policy should be written down and owned by someone. In most companies today, the effective dependency policy is whatever the person who configured the bot three years ago happened to choose. That’s a strange place to leave a decision that CISA now writes advisories about.
The honest counterargument: someone has to go first
Cal Paterson raised the sharpest objection to cooldowns: they free-ride on the pain of others. Detection windows are short precisely because early adopters exist and get burned. If everyone waits seven days, nobody triggers the alarms, and attackers simply wait out the delay. His proposed alternative is upload queues: the registry itself delays distribution after publication, giving scanners a guaranteed inspection window. Woodruff concedes this design is better; it’s also much harder to retrofit onto npm’s economics. Notably, GitHub’s post-Shai-Hulud hardening roadmap for npm is all authentication and tokens, with no registry-level quarantine anywhere in it.
I take the free-riding point seriously and adopt cooldowns anyway. Malicious versions today are detected mostly by automated scanning from security vendors, not by victims filing bug reports, so mass cooldown adoption degrades detection less than the argument implies. And a dormant malicious package gives scanners more time, not less. But it’s a real tension, and if registry-level quarantine ever ships, it deserves to win.
When this doesn’t apply
If you ship a quarterly desktop application from a repo with thirty dependencies, you can review updates by hand and none of this machinery earns its keep. If you run an air-gapped environment with a curated internal registry, you already have a cooldown; it’s called your mirroring process. And if your product is itself a fast-moving library, you may have obligations to test against fresh releases of your peers that override a waiting period. The tiered policy is for the common case: a service-shipping organization with hundreds of transitive dependencies and an update bot that currently merges whatever arrives.
Where this leaves us
The instinct we trained into teams, “updating promptly is a security practice,” is still true. It’s just no longer the whole truth. Updating promptly is a security practice for known vulnerabilities and an attack surface for unknown ones, and the difference between the two is about seven days of patience.
The teams that got through September 2025 cleanly weren’t the ones with the best scanners. They were the ones whose dependencies were, by policy or by accident, a week behind. I’d rather that be policy.