"Describing install-time lifecycle scripts as the 'single largest code-execution surface in the npm ecosystem,' GitHub said the 'npm install' command runs scripts from every transitive dependency," GitHub said, making the case for a default change in behavior.
GitHub's specific changes scheduled for npm 12
GitHub announced a set of "breaking changes" that will ship with npm version 12, scheduled for release next month. The headline items are concrete and narrow in scope:
- npm install will no longer execute preinstall, install, or postinstall scripts from dependencies unless they are explicitly allowed in the project.
- npm install will no longer resolve Git dependencies, direct or transitive, unless explicitly allowed via --allow-git.
- npm install will no longer resolve dependencies from remote URLs (for example, https tarballs) unless explicitly allowed via --allow-remote.
The announcement also notes that native node-gyp builds will be affected because npm runs an implicit node-gyp rebuild; a package with a binding.gyp and no explicit install script will still be blocked under the new default. Prepare scripts from git, file, and link dependencies are blocked the same way, the Microsoft-owned subsidiary said.
Why GitHub is turning off install scripts by default
GitHub framed the change as a direct defense against supply chain abuse. Because npm install runs scripts from every transitive dependency, "a single compromised package anywhere in the dependency tree can run arbitrary code on a developer machine or CI runner," the company said. By making script execution opt-in, GitHub intends to require explicit user approval before code executes automatically during an install rather than trusting lifecycle hooks by default.
"Making script execution opt-in closes that path while keeping it one command away for the packages you trust," GitHub added, summarizing the trade-off between safety and convenience.
Developer guidance and migration steps from GitHub
GitHub provided a clear migration path for projects that will be affected. It recommends upgrading to npm 11.16.0 or newer now, running a normal install, and reviewing the warnings that appear. Developers are instructed to use the command:
- npm approve-scripts --allow-scripts-pending
to list packages that have install-time scripts, approve those they trust, and then commit the updated package.json. According to GitHub, "after that, only the scripts you approved keep running once you upgrade. Anything you leave unapproved will stop."
The announcement also recalled an earlier change introduced this year: npm's "min-release-age" setting, which tells npm to reject any package version published less than a specified number of days as an additional safeguard against newly published malicious packages.
What this means for technologists, CI teams, and open-source maintainers
- Technologists and security teams: Expect an inventory task. Running npm 11.16.0 and using npm approve-scripts will identify which transitive dependencies rely on lifecycle scripts. Teams will need to approve trusted scripts and accept that unapproved scripts will stop once npm 12 is adopted.
- CI teams and DevOps: Automated build and test runners that rely on install-time scripts or implicit native builds (node-gyp) may see failures unless projects explicitly allow the required scripts or adjust CI policies to grant approvals.
- Open-source maintainers: Packages that rely on preinstall/install/postinstall hooks, Git-hosted dependencies, or remote tarball installs will either need to document those requirements or adapt to the new defaults so downstream consumers can approve them deliberately.
Operational impact of blocking Git and remote URL dependencies
GitHub said it will default "--allow-git" to "none," closing a specific execution path where a Git dependency's .npmrc configuration could override the Git executable — a vector that could be exploited even with --ignore-scripts set. By requiring explicit --allow-git or --allow-remote, npm 12 places an additional manual gate on two common, previously implicit sources of code that run at install time.
GitHub's approach preserves a path back to convenience — scripts remain "one command away" — while shifting the default toward explicit trust. The immediate practical step it prescribes is concrete: upgrade to a supported npm 11 release, run installs, review warnings, approve known-good scripts with npm approve-scripts, and commit the resulting package.json before moving to npm 12. Whether that workflow reduces real-world supply chain compromises will depend on how quickly projects adopt the approvals process and how consistently CI and maintainers adjust to the new defaults.




