On June 9, GitHub announced the breaking changes coming in npm v12, estimated for July 2026. They are the most consequential security changes npm has shipped in years, and they all say the same thing: install-time trust stops being implicit.
- Dependency install scripts stop running by default.
preinstall,install,postinstallfrom dependencies need explicit approval in a committedallowScriptspolicy in package.json. Even native builds are included: a package with abinding.gypgets blocked, because npm runs an implicitnode-gyp rebuildfor it. - Git dependencies stop resolving unless allowed via
allow-git. The rationale is precise: a git dependency's own.npmrccan override the git executable, a code-execution path that survives--ignore-scripts. - Remote URL tarballs stop resolving unless allowed via
allow-remote.
Everything is preparable today on npm 11.16.0+, where the new behavior runs in warning mode. If the pattern sounds familiar, it should: this is the model pnpm v11 shipped, arriving at the ecosystem's default package manager. After node-ipc in May, the AntV burst, and the Miasma worm in June, all of which entered through install-time execution, the default finally moved.
The new question: who reviewed the policy?
Explicit trust is a real improvement, and it relocates the problem rather than ending it. The policy lives in files the repository ships: allowScripts in package.json, allow-git and friends in a committed .npmrc. Which means a repo can weaken its own policy, for everyone who clones it, with one committed line:
dangerously-allow-all-scripts=true # npm's own escape hatch, left committed
Or more quietly: an allowScripts approval written by name only, which approves every future version of a package instead of the version someone actually reviewed. Or allow-git=all pinned in .npmrc, carrying the relaxed behavior straight through the v12 upgrade.
This is the trust-layer pattern we keep running into: the artifact that grants trust is obeyed, not reviewed. Naming that layer was step one. npm v12 just added four new files worth of it.
What Aguara checks
Aguara's npm-policy analyzer reads package.json and the project .npmrc and flags install-trust decisions weakened below the npm v12 baseline:
| Rule | Severity | What it flags |
|---|---|---|
NPM_DANGEROUS_ALL_SCRIPTS_001 | HIGH | dangerously-allow-all-scripts=true: the documented migration escape hatch, bypassing the policy entirely |
NPM_ALLOW_SCRIPTS_UNPINNED_001 | MEDIUM | Name-only allowScripts approvals (or allow-scripts-pin=false): tomorrow's compromised release inherits today's approval |
NPM_ALLOW_GIT_RELAXED_001 | MEDIUM | allow-git=all|root committed, pinning git resolution open against the v12 default |
NPM_ALLOW_REMOTE_RELAXED_001 | MEDIUM | allow-remote=all|root, same for remote tarballs |
A missing setting never fires. A repo that simply runs npm's defaults stays clean; the analyzer reports only explicit choices that broaden trust. Every parser behavior was verified against real npm 11.16.0 rather than assumed, down to the details: a deny entry is never confused with an unpinned approval, an inline comment does not hide a live setting, repeated keys resolve the way npm resolves them, and a hand-typed wildcard that npm ignores stays silent.
Readiness, not just risk
There is a second half, and it is not about attacks. A project that depends on git sources or URL tarballs today will simply stop installing under npm v12 until someone grants the exceptions. Two INFO-level findings turn that into a migration list:
$ aguara scan .
INFO package.json:14 NPM_GIT_INSTALL_TRUST_001
dependencies.viz resolves from a git source.
npm v12 will require an explicit allow-git exception.
INFO package.json:15 NPM_REMOTE_INSTALL_TRUST_001
dependencies.blob resolves from a remote URL tarball.
npm v12 will require an explicit allow-remote exception.
INFO severity never fails a default CI gate: these findings inform the upgrade, they do not block it. The classification follows npm's actual install gates, which hold a few surprises we confirmed against the real tool: a repository URL on GitHub or GitLab is a git dependency even without a .git suffix, while an archive or release-download URL on the same host is a remote tarball, and a .git URL on an unknown host is remote unless it uses a git+ scheme.
Before install, before CI, before delegation
npm is making install-time trust explicit. Aguara helps teams review that trust before install, before CI runs it, and before an agent inherits it: the same scan covers the npm policy files, the pnpm posture, the lockfiles, and the agent configuration a repo ships.
$ aguara audit . --ci
One run, before anything executes. That is the point of the layer.
Is your repo ready for npm v12?
aguara scan . reviews the install-trust policy and lists the exceptions the upgrade will require.