Skip to content

feat: Phase 1 of allowScripts opt-in install-script policy (#9360)#9415

Merged
owlstronaut merged 1 commit into
release/v11from
backport/v11/9360
May 27, 2026
Merged

feat: Phase 1 of allowScripts opt-in install-script policy (#9360)#9415
owlstronaut merged 1 commit into
release/v11from
backport/v11/9360

Conversation

@owlstronaut
Copy link
Copy Markdown
Contributor

Backports #9360 to v11.

@owlstronaut owlstronaut requested review from a team as code owners May 27, 2026 15:22
Implements Phase 1 of
[npm/rfcs#868](npm/rfcs#868), which makes
dependency install scripts opt-in.

**Install behaviour is unchanged.** Scripts still run as they always
have. The only Phase 1 user-visible change is one advisory block at the
end of `npm install` listing packages whose install scripts haven't been
reviewed via the new `allowScripts` field in `package.json`. A future
release will turn that advisory into an actual block.

- `allowScripts` field in `package.json`, read at install time
- Three new configs: `allow-scripts`, `strict-script-builds`,
`dangerously-allow-all-scripts`. The latter two are no-ops in this
release. They're registered so projects can pin them in tooling ahead of
the release that flips the default.
- `npm approve-scripts` and `npm deny-scripts` commands, with the RFC's
asymmetric pin rule (approves can pin, denies are always name-only)
- Advisory warning during `npm install`, `ci`, `update`, and `rebuild`.
`npm exec` / `npx` consult only the user/global `.npmrc` layer per the
RFC, with the policy threaded through libnpmexec for Phase 2
enforcement.
- Identity matcher in `@npmcli/arborist` covering registry, git, file,
and remote tarballs. Registry identity is derived from the lockfile's
resolved URL (via `versionFromTgz`), never from `node.packageName` or
`node.version`. Those getters read the installed tarball's
`package.json` and can be forged.
- Aliases match against the underlying registered package, not the alias
name. `trusted@npm:naughty@1.0.0` is approved by writing `naughty`, not
`trusted`. Holds even under `omitLockfileRegistryResolved`, where the
install location alone (`node_modules/trusted`) would be misleading. The
underlying name is derived from the incoming edge's alias `subSpec`.
- Bundled deps with install scripts are flagged as unreviewed and
filtered out of `npm approve-scripts --all` and positional matches. Per
RFC they cannot be allowlisted in Phase 1.
- Warning when a non-root workspace declares its own `allowScripts`

- Actual blocking. The matcher exists and the policy is threaded through
to arborist, but `arb.rebuild()`'s build set still runs everything.
Phase 2 will gate `#addToBuildSet` on the matcher.
- A safe allowlist syntax for bundled deps. The RFC notes a candidate
`parent@1.2.3 > bundled-name` form for a follow-up.

Refs: npm/rfcs#868
(cherry picked from commit 7068d42)
@owlstronaut owlstronaut merged commit a10c7ca into release/v11 May 27, 2026
64 checks passed
@owlstronaut owlstronaut deleted the backport/v11/9360 branch May 27, 2026 16:03
@github-actions github-actions Bot mentioned this pull request May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants