DEV Community

Cover image for chalk and debug shipped malware for a few hours. Waiting 7 days would have skipped it.
Versyka
Versyka

Posted on Edited on AI-assisted

chalk and debug shipped malware for a few hours. Waiting 7 days would have skipped it.

In September 2025, a maintainer of several very popular npm packages, including chalk and debug, had their account phished. New versions were published with code that tried to steal cryptocurrency from browsers. The community spotted it quickly, and the bad versions were removed within hours.

The teams that got hit were the ones whose installs ran in those hours. Teams that waited even a couple of days never saw the bad versions at all.

Most bad releases have a short life

Not every bad release is an attack. Most are ordinary mistakes: a broken build published by accident, a regression the tests missed, a missing file. The pattern is the same:

day 0   release published
day 1   issues opened, maybe a security report
day 2   version deprecated or unpublished, fix released
Enter fullscreen mode Exit fullscreen mode

So a simple rule removes most of the risk: don't install a release until it's a few days old. Seven days is a common choice.

Setting it up

Renovate has it built in:

{
  "minimumReleaseAge": "7 days"
}
Enter fullscreen mode Exit fullscreen mode

Dependabot has a cooldown option in dependabot.yml for the same idea:

updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 7
Enter fullscreen mode Exit fullscreen mode

Lockfiles do the rest: with npm ci and a committed package-lock.json, nothing new is installed until a pull request changes the lockfile.

The exception: security fixes

A release that patches a known vulnerability is a different trade-off: the risk is in not installing it. Keep a separate, faster path for security updates, and review them like any other change.

If you installed it in that window

The payload hooked browser wallet calls and swapped addresses, so the real exposure was frontends built during those hours, not Node services. Checking the lockfile isn't enough: the bad code shipped inside the bundle and kept running on users' machines until the next deploy.

  1. Find every frontend build and deploy from those hours (CI history and deploy timestamps).
  2. Rebuild from a clean lockfile and redeploy, rather than only bumping the version.
  3. Purge CI dependency caches and CDN caches, so the old node_modules or the old bundle doesn't come back.

What we do

Versyka's weekly upgrades collect minor and patch updates that are at least 7 days old and open them as one tested pull request, while security fixes take their own path. More in the docs.

Does your dependency bot install releases the day they come out?

Top comments (2)

Collapse
 
cryptostrapon profile image
cryptostrapon •

The payload in that incident hooked browser wallet calls and swapped addresses, so the exposure was mostly frontends built in those hours rather than Node services. Anyone checking whether they were hit should look at the bundles shipped in that window, not only the lockfile.

Collapse
 
getversyka profile image
Versyka •

Good point, and it changes what "check your lockfile" should mean here. The payload only did anything where a browser wallet was present, so a Node API that installed the bad version was mostly exposed in name only. A frontend built in that window is different: the code shipped inside the bundle and kept running on users' machines until the next deploy, even after the lockfile was fixed.

So the practical check is:

  1. Find every frontend build and deploy from those hours (CI history and deploy timestamps).
  2. Rebuild from a clean lockfile and redeploy, rather than only bumping the version.
  3. Purge CI dependency caches and CDN caches, so the old node_modules or the old bundle doesn't come back.

Thanks for adding this. I'll fold it into the article.

⌂ 换网址