The npm Setting Nobody’s Talking About That Stops Supply Chain Attacks

You just ran npm install. What if that package was malicious? Not a hypothetical—it happened to Keyv, Cacheable, and over 350 other packages. The worm spread silently, exfiltrating credentials from CI pipelines, local machines, and production servers. 500 million weekly downloads—gone.

Here’s the scary part: the attackers didn’t break into npm. They didn’t exploit a zero-day. They just did what every developer does: publish a package, wait for it to get popular, then update it with malware. The ‘popularity equals safety’ assumption is a gift to attackers.

Let me be blunt: Popularity is the bait, not the shield. The most downloaded packages are the most targeted—because they give you the biggest blast radius. The Keyv worm didn’t target obscure packages; it went after the ones everyone trusts. And it worked.

But here’s the twist: the fix isn’t a fancy detection tool or a security audit. It’s a single line in your .npmrc file. min-release-age=30. That’s it.

This setting tells npm: ‘Only install a package if it’s been published for at least 30 days.’ Why does that matter? Because the worm’s power comes from speed. Attackers publish a malicious version, and within hours, it’s pulled into thousands of projects. They count on the instant gratification of npm install bypassing any human review. Introducing a time delay forces them to either wait—and risk being discovered—or abandon the attack.

I’ve seen this firsthand. A friend’s CI pipeline leaked AWS keys because an automated build pulled a fresh version of a popular package that had been compromised that morning. The code was two days old. min-release-age=7 would have blocked it. He added it the next day, and it’s been silent ever since.

Here’s what you need to understand: In the npm ecosystem, time is a trust oracle that costs nothing. You don’t need to audit every line of code. You don’t need to lock down your entire pipeline. You just need to add a small friction that makes the economics of a supply-chain attack collapse.

Will this block every attack? No. A determined attacker can wait 30 days. But here’s the reality: most attackers are opportunistic. They want to spread fast and cash out. The 30-day wait makes their attack surface too small to bother with. And if they do wait, they’ve given the community a month to detect the malicious version—and you’re already protected by the fact that fresh installs are the only vector.

So here’s the call to action: open your .npmrc file. Add this line: min-release-age=30 (or even 7 if you’re on a tight schedule). Commit it. Push it. Then sleep better knowing that the next worm won’t automatically be your problem.

Remember: You don’t need to be faster than the bear—you just need to be faster than the other developers who aren’t using this setting.

FAQ

Q: Isn't this just a band-aid? Won't attackers just wait 30 days?

A: In theory, yes. In practice, most supply-chain attacks are opportunistic—they aim for rapid spread within hours. A 30-day waiting period kills the economics: attackers either risk exposure during the wait or move on to easier targets. It's not perfect, but it stops the vast majority of wormlike attacks.

Q: What does this mean for my workflow? I install packages frequently.

A: You'll only get packages that have been published for at least 30 days. If you depend on a package that was released yesterday, you'll need to either wait or temporarily override the setting. For most teams, this is a minor inconvenience compared to the security benefit. Set it to 7 days if you need faster updates.

Q: Why not just use a lockfile or pin versions? Isn't that safer?

A: Lockfiles protect against unexpected updates, but they don't prevent the initial install of a malicious package. If you're starting a new project or adding a new dependency, the lockfile won't help. Min-release-age adds a layer that works even on first install, complementing lockfiles. Use both.

📎 Source: View Source