Minor Changes
-
Treat tarball-integrity mismatches against the lockfile as a hard failure by default. Previously,
pnpm install(non-frozen) would logERR_PNPM_TARBALL_INTEGRITY, silently re-resolve from the registry, and overwrite the locked integrity — which meant a compromised registry, proxy, or republished version could substitute attacker-controlled content on a clean machine even though the project shipped a committed lockfile.pnpm installnow exits withERR_PNPM_TARBALL_INTEGRITYand a hint pointing at the new opt-in flag.The only opt-in is
pnpm install --update-checksums— narrowly scoped to refreshing the locked integrity values from what the registry currently serves. Mirrors yarn's flag of the same name. A warning still prints when the bypass takes effect so the operation is auditable.--forceandpnpm updatedeliberately do not bypass the integrity check. They are routine refresh operations; silently overwriting a locked integrity in those flows would erase the protection a committed lockfile is supposed to provide.--frozen-lockfilebehavior is unchanged.--fix-lockfilekeeps its documented purpose (filling in missing lockfile entries) and is also not a bypass. -
pnpm runtime set <name> <version>now saves the runtime todevEngines.runtimeby default instead ofengines.runtime. Pass--save-prod(or-P) to save it toengines.runtimeinstead #11948.
Patch Changes
-
Fix a credential disclosure issue where an unscoped
_authToken(or_auth, orusername+_password, ortokenHelper) defined in one source —~/.npmrc,~/.config/pnpm/auth.ini, a workspace.npmrc, CLI flags, etc. — would be sent as anAuthorizationheader to whichever registry a different (potentially untrusted) source named. The same fix extends to client TLS credentials (cert,key) so they aren't presented to a registry their author didn't choose.pnpm now rewrites each unscoped per-registry setting (
_authToken,_auth,username,_password,tokenHelper,cert,key) to its URL-scoped form at load time, using theregistry=value declared in the same source (or the npmjs default registry if the source declares none). A later layer overridingregistry=therefore cannot pull an unscoped credential along, because it is already pinned to the URL its author intended.ca/cafileare intentionally not rescoped — they're trust anchors, not credentials, and corporate MITM-proxy setups rely on them applying globally.Every rescope emits a deprecation warning telling the user where the setting was pinned and how to write it directly. npm has rejected unscoped credentials outright since
npm@9, and pnpm intends to remove support in a future major release. To target a specific registry, write the setting URL-scoped (e.g.//registry.example.com/:_authToken=...or//registry.example.com/:cert=...).@pnpm/network.auth-header: removed thedefaultRegistryparameter fromcreateGetAuthHeaderByURIandgetAuthHeadersFromCreds. Now that credentials are URL-scoped at load time, the mergedconfigByUrinever contains the empty-string "default registry" placeholder slot, so re-keying it onto the merged default registry is no longer needed. -
Fix
pnpm deploycrashing withENOENT: ... lstat '<deployDir>/node_modules'whenconfigDependenciesdeclares pacquet (pacquetor@pnpm/pacquet). The deploy directory never installs config dependencies, so the install engine they designate isn't on disk to invoke; the nested install now skips them. -
Reject git resolutions whose
commitfield is not a 40-character hexadecimal SHA before invokinggit. A malicious lockfile could otherwise smuggle a value such as--upload-pack=<command>throughgit fetch/git checkout, which on SSH or local-file transports executes the supplied command. -
Limit concurrent project manifest reads while listing large workspaces to avoid
EMFILEerrors. -
Reject patch files whose
diff --githeaders reference paths outside the patched package directory. Previously a malicious.patchfile added via a pull request could write, delete, or rename arbitrary files reachable by the user runningpnpm install. -
Improve the log message that pnpm prints after auto-adding entries to
minimumReleaseAgeExcludewhenminimumReleaseAgeis set withoutminimumReleaseAgeStrict. The message previously referred to the internal "loose mode" terminology, which wasn't searchable in the docs; it now tells the user to setminimumReleaseAgeStricttotrueif they want these updates gated behind a prompt instead #11747. -
Reject dependency aliases that contain path-traversal segments (such as
@x/../../../../../.git/hooks) when reading them from a package manifest or symlinking them intonode_modules. A malicious registry package could otherwise use a transitive dependency key to makepnpm installcreate symlinks at attacker-chosen paths outside the intendednode_modulesdirectory. -
Reject
pnpm-lock.yamlentries whose remote tarballresolution:block is missing theintegrityfield. Previously the worker that extracts a downloaded tarball skipped hash verification when no integrity was supplied and minted a fresh one from the unverified bytes, so an attacker who could both alter the lockfile (e.g. via a pull request that stripsintegrity:) and serve modified content at the referenced tarball URL could install a tampered package without any error — including under--frozen-lockfile. pnpm now fails closed at lockfile-read time withERR_PNPM_MISSING_TARBALL_INTEGRITY. Git-hosted tarballs (gitHosted: trueor a URL on codeload.github.com / bitbucket.org / gitlab.com) andfile:tarballs are exempt — the commit SHA in a git-host URL and the user-controlled local path already anchor the bytes. -
Validate
devEngines.runtimeandengines.runtimeversion ranges fornode,deno, andbunwhenonFailis set toerrororwarn. Previously these settings only had an effect withonFail: 'download'— theerrorandwarnmodes silently did nothing #11818. Violations now throwERR_PNPM_BAD_RUNTIME_VERSION. -
Require provenance before treating trusted publisher metadata as the strongest trust evidence.
Platinum Sponsors
|
|
Gold Sponsors
|
|
|
|
|
|
|
|
|
|
|