Constance Bello

Rebel technologist

About / Blog (List of tags)


Mitigating supply chain attacks with package cooldowns

2026-08-17 / tags: security, technical, quick reads, guides

A package emoji, color-shifted to be bright red, in front of a fire emoji.

Software developers and the libraries and applications they write are prime targets for attackers seeking to grab all sorts of valuable prizes: cloud service credentials, downstream users, cryptocurrency wallet keys, networks of all kinds... the list goes on and on. As such, software supply chain attacks have been ramping up for the past several years, and they're now reaching a fever pitch. I can't recall a month of this year I didn't read about a popular software library getting compromised, leading to downstream libraries and applications being accessed by the attacker in turn.

Fear not, though! Waiting to use new versions of software packages for a time after they are published can help avoid getting pwned by a supply chain attack. Updates to dependency management tools for a variety of programming languages allow this to happen automatically as part of regular dependency updates, meaning this protection doesn't come at the expense of a smooth workflow. This post includes quick guides on how to do this with project tooling for JavaScript, Python, and Ruby. I plan to update this post as more tools add this function.

One general note: in most of these implementations, specific packages can be made exempt from the cooldown; however, there is no way to only allow a specific package version to bypass – each package is either set as exempt, meaning any appropriate version will do, or not, meaning the cooldown applies. This is far from ideal and I hope that these tools start adding ways to specify specific version ranges that can bypass the cooldown to cherry-pick security fixes without sacrificing the benefits of the cooldown. In any case, I'll get into specifics on how to exempt packages from cooldown for each language in its corresponding section. Without further ado, let's begin!

JavaScript

There are several JavaScript package managers to work through, so let's tackle them one by one:

pnpm

pnpm supports

Node.js

This functionality is built right in to npm! To set a package cooldown, throw this in your Node project's .npmrc:

; .npmrc
min-release-age=7 ; Don't update to new package versions until 7 days after they were released

If you'd like to make my-invulnerable-javascript-package and another-package exempt from the cooldown, add this in there too:

; .npmrc
; Exempt my-invulnerable-javascript-package and another-package from the cooldown
min-release-age-exclude[]=my-invulnerable-javascript-package
min-release-age-exclude[]=another-package

This is documented in npm's configuration documentation in the sections on min-release-age and min-release-age-exclude.

Now, this is JavaScript we're talking about, so we have to do this several other ways too...

pnpm

Python

pip with a requirements.txt file isn't going to be of much use here, unfortunately, but we can instead use the leveled up dependency management tool for Python, Poetry. The relevant option for setting a package cooldown is in Poetry's configuration. In your Poetry project's config.toml, add this key:

# config.toml
# Don't update to new package versions until 7 days after they were released
[solver]
min-release-age = 7

If you'd like to make my-invulnerable-python-package and another-package exempt from the cooldown, add this in there too:

# config.toml
# Exempt my-invulnerable-python-package and another-package from the cooldown
[solver]
min-release-age-exempt = "my-invulnerable-python-package,another-package"

This is documented in Poetry's configuration documentation, in the sections on [solver.min-release-age] and [solver.min-release-age-exclude].

Ruby