GitHub Overhauls npm Defaults to Block Malicious Auto-Run Scripts
GitHub is fundamentally altering npm's default behavior to disable automatic script execution during package installation, a move designed to curb widespread exploitation of malicious packages.

GitHub is implementing significant changes to the default behavior of npm, the package manager for Node.js, aiming to drastically reduce the attack surface exploited by malicious packages. Starting with npm version 12, scheduled for release in July, the npm install command will no longer automatically execute scripts like preinstall, install, or postinstall without explicit user consent. This change directly addresses a major vulnerability that has plagued the JavaScript ecosystem, where compromised dependencies could previously execute arbitrary code on developer machines and CI/CD pipelines.
Maintainer Leo Balter highlighted the severity of the issue, stating, "Install-time lifecycle scripts are the single largest code-execution surface in the npm ecosystem." The previous default allowed any package within a project's dependency tree, even deeply nested ones, to run potentially harmful code during the installation process. This has been a primary vector for malware, including notorious threats like the Shai-Hulud worm, which leveraged these scripts for widespread infection.
The new default behavior requires users to explicitly opt-in to script execution by using an allow-scripts configuration. This provides a much-needed layer of security, forcing developers to consciously approve the execution of scripts from their dependencies. While this is a breaking change, it is a critical step towards a more secure npm ecosystem. Developers are advised to run commands to allow scripts for currently installed packages to prepare for the update and immediately gain protection against new, unexpected scripts.
Beyond script execution, npm 12 will also introduce stricter defaults for remote dependencies and Git integration. The --allow-git flag, which enables pulling dependencies from remote URLs, will default to off. This closes an attack vector where a malicious .npmrc file could override the Git executable to achieve arbitrary code execution. Additionally, the allow-remote setting will default to none, completely blocking dependency downloads from remote URLs. These changes aim to prevent supply chain attacks that rely on manipulating dependency sources.
While the new defaults enhance security, some packages will require explicit script approval to function correctly. This includes native modules that compile on install, testing tools like Playwright and Puppeteer that fetch binaries during installation, and frameworks like Electron, which bundle Chromium. These packages have relied on install scripts for essential setup. Users will need to review their dependencies and selectively enable scripts where necessary, potentially pinning script approval to specific package versions for added safety.
These security enhancements have roots in earlier versions of npm. Version 11.10.0, released in February, introduced opt-in flags for similar security measures, including min-release-age, which blocks the installation of packages newer than a specified number of days to act as a safeguard against newly published malicious packages. Best practices for developers using current versions involve setting these flags in .npmrc or via environment variables to prepare for the upcoming defaults in npm 12.
Despite the significant improvements, some in the developer community express concerns that malware might simply shift its focus from install scripts to the package code itself, which would still be executed. Others point to alternative package managers like pnpm, which already implement safer defaults. However, there is a general consensus that these changes are long overdue and represent a substantial upgrade in npm's security posture, bringing it more in line with other major package managers like pnpm, Yarn Berry, Bun, and Deno, which already block dependency install scripts by default.