pnpm 11 Made the Safe Thing the Default

Protecting against supply chain attacks requires vigilance. You have to audit your dependencies. You have to pin your versions. You have to review your install scripts. All of these are great things to do, but they require sustained effort.

pnpm 11 took the obvious thing and made it the default. They changed the waiting period. minimumReleaseAge defines the minimum number of minutes that must pass after a version is published before pnpm will install it.

Before version 11 the default was 0. In version 11 the default is 1440 minutes, which is 24 hours, and it applies to everything.

Most malicious packages get discovered and pulled from the registry within minutes, or at most an hour. So what a day of patience buys you is that you’ve eliminated the potential for dependencies sneaking in that haven’t been fully vetted.

npm already followed suit, and so did everyone else. This is now table stakes across the ecosystem:

  • pnpm got there first with minimumReleaseAge, measured in minutes, back in 10.16 in September 2025.
  • Yarn shipped npmMinimalAgeGate, also minutes, in 4.10.0 that same month.
  • Bun added minimumReleaseAge in 1.3 in October 2025, measured in seconds, plus a minimumReleaseAgeExcludes list for packages you trust.
  • npm landed min-release-age in 11.10.0 in February 2026, measured in days.

I guess they couldn’t agree on the unit of time for their release age setting.

As far as I know, in all of them besides pnpm, the cooldown is opt-in. It’s not the default. So you have to know the setting exists and you have to go turn it on.

Here are some other things that changed in pnpm 11:

  • allowBuilds replaces onlyBuiltDependencies, which was removed in v11. It’s a map of which packages may run build scripts. Anything not listed is disallowed and treated as unreviewed.
  • strictDepBuilds defaults to true. Installation exits with a non-zero code if any dependency has unreviewed build scripts, so this fails your CI rather than printing a warning nobody reads.
  • verifyDepsBeforeRun defaults to install. Before pnpm run or pnpm exec, it checks whether your dependency state matches the lockfile. Other options are warn, error, prompt, and false.
  • dangerouslyAllowAllBuilds defaults to false, and the name is doing exactly the work it should. Setting it true lets every dependency, transitive ones included, run install scripts now and in the future.

The clear pattern here is that an automated or unintentional action should be blocked, not permitted with a warning.

Sure, there is somewhat of a cost here. The delay means you can’t immediately install a new version that was just published unless you flip the flag. I can see the allowBuilds migration being somewhat of a hassle, because the first time you install after upgrading you’re going to get a list of packages that want to run build scripts. It’s easy to be lazy and approve all of them without thinking.

With the tools we have available to us these days, we can ask an agent to review the build scripts. This is the right thing to do. Find a way to pin the dependency to fix transitive version issues. The inner engineer in all of us needs to understand why build scripts are dangerous, and what to be careful of, so that you can ask your subagent to go and see if that’s a problem, or if that problem has been fixed with the new version. It’s up to the human in the loop to ensure that the agents are doing their due diligence.

When building software, we should also look for other paths to optimize, and make the lazy path the safest one, because chances are that’s going to become the default.

I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].

security javascript Tooling Supply-chain Nodejs