The Three Hour Attack Window npm Leaves Open by Default
In late March 2026, an attacker hijacked the npm account of axios's lead maintainer and published backdoored versions of the library. Axios has 100 million weekly downloads. The packages were live for about three hours before being pulled, with CISA and Singapore's CSA both issuing advisories.
npm has no minimum version age by default, so any developer or pipeline that ran npm install during that window picked up the malicious versions automatically. By May 2026 attacks like this were self-replicating; a worm tore through packages from @tanstack, @mistralai, @uipath and others, growing to over 600 compromised package versions. It spread by stealing CI/CD tokens from each victim and using them to publish backdoored versions of other packages they had write access to.
The pattern is the same every time: push a malicious version and wait for developers or CI pipelines to install it, and that window doesn't need to be long.
The Strongest Fix
The defence against all of these attacks is the same, set a minimum release age so that newly published package versions are blocked from being installed until enough time has passed for the community to catch them.
npm 11.10.0 added a native option for this:
npm config set -L project min-release-age=3 # days
npm will refuse to install any package version published less than three days ago. The axios backdoor and the May worm's freshly published versions would have been skipped automatically. Three days is a sensible default for most teams, but drop it to one if your team needs tighter upgrade cycles.
Yarn (v4.10.0+) supports the same setting in .yarnrc.yml:
npmMinimalAgeGate: "3d"
As does pnpm (v10.16.0+) in pnpm-workspace.yaml, and notably pnpm ships with a one-day minimum already enabled by default:
minimumReleaseAge: 4320 # 3 days; default is 1440 (1 day)
For Python, Rust, Go, Maven and every other ecosystem, cooldowns.dev has configuration snippets for each package manager.
This won't catch every case, as packages that download and execute dependencies at runtime bypass the gate entirely (or a patient attacker can simply wait out the window), but it reliably helps harden against the fast propagation attack pattern behind most real world supply chain incidents.
Dam Secure flags it before it gets missed
Most teams configure this on their main repositories and consider it done, but the real risk is the service that gets missed: a new microservice spun up quickly, or a repo that predates the policy, where the configuration was never applied and nobody noticed.
Dam Secure scans every repository and surfaces missing package age enforcement as a finding, with the remediation included. It works across ecosystems, so whether a repo uses npm, pip or something else, the gap gets caught and flagged before it even reaches a pull request.
Supply chain hardening shouldn't depend on someone remembering to apply a config change to every new repo they create, and with Dam Secure it doesn't.
