GitHub Hardens npm Against Supply Chain Attacks with Default Script Blocking
In a significant move to bolster software supply chain security, **GitHub** is implementing 'breaking changes' in **npm** version 12, scheduled for release next month. The update will disable the automatic execution of install scripts by default, directly addressing a critical attack vector abused by malicious packages.
Software supply chain security has become a paramount concern for IT security professionals, with **npm**'s package manager being a frequent target. **GitHub**, the custodian of **npm**, is taking decisive action to mitigate these risks by introducing 'breaking changes' in the upcoming **npm** version 12.

### Disabling Install Scripts by Default
The core of the update lies in turning off install scripts by default. This change directly combats attack techniques that leverage the `npm install` command to trigger malicious code execution via **npm** lifecycle hooks. **GitHub** has identified install-time lifecycle scripts as the "single largest code-execution surface in the **npm** ecosystem."
Currently, `npm install` runs scripts from every transitive dependency, meaning a single compromised package anywhere in the dependency tree can execute arbitrary code on a developer's machine or CI runner. By blocking these behaviors, **npm** will now require explicit user approval before code execution is initiated automatically during installation.
### Key Changes in npm v12
The upcoming changes are comprehensive and target several common attack vectors:
* `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, whether direct or transitive, unless explicitly allowed via `--allow-git`.
* `npm install` will no longer resolve dependencies from remote URLs, such as `https` tarballs, unless explicitly allowed via `--allow-remote`.
This also extends to native `node-gyp` builds, where a package with a `binding.gyp` but no explicit install script will still be blocked, as **npm** implicitly runs a `node-gyp rebuild` for it. Similarly, `prepare` scripts from **Git**, file, and link dependencies will be blocked.
### Mitigating Git Dependency Exploits
By defaulting `--allow-git` to `none`, **GitHub** closes a crucial code execution path where a **Git** dependency's `.npmrc` configuration file could override the **Git** executable. This vulnerability existed even with the `--ignore-scripts` flag, which is designed to prevent packages from automatically running built-in lifecycle scripts during installation.
### Developer Preparation and Best Practices
**GitHub** recommends that developers prepare for these changes by upgrading to **npm** 11.16.0 or newer. After upgrading, developers should run a normal install and review any warnings displayed. The advised workflow is to use `npm approve-scripts --allow-scripts-pending` to identify packages with scripts, approve trusted ones, and then commit the updated `package.json`.
Only explicitly approved scripts will continue to run after the upgrade, while unapproved scripts will be blocked. This shift from implicit trust to explicit approval significantly enhances the security posture of the **npm** ecosystem.
Earlier this year, **npm** also introduced `min-release-age`, a setting designed to reject any package version published less than a specified number of days. This acts as an additional safeguard against newly published malicious packages, further fortifying the software supply chain.