Summary of Events
For over 15 years, npm allowed packages to execute arbitrary code during installation through preinstall, install, and postinstall scripts. These scripts ran automatically whenever a developer typed npm install, creating a vulnerability for supply chain attacks. GitHub announced in early 2025 that npm will block automatic execution of these scripts starting in July, requiring explicit approval for any third-party package scripts to run.
This change wasn't triggered by a single incident but is a response to years of supply chain compromises exploiting npm's permissive defaults. Competitors like Yarn, pnpm, and Bun had already implemented similar protections.
Timeline
2009-2024: npm allowed install scripts to execute automatically by default. While many packages used this for legitimate purposes, attackers exploited it to exfiltrate credentials, install backdoors, and compromise environments.
2021-2024: High-profile supply chain attacks exploited automatic script execution. Typosquatting packages, dependency confusion attacks, and compromised maintainer accounts all took advantage of npm install running code without user intervention.
2024: Competing package managers (Yarn, pnpm, Bun) blocked install scripts by default, pressuring npm to follow suit.
Early 2025: GitHub announced the default change, giving teams roughly six months to prepare.
July 2025: npm's new default takes effect. Install scripts require explicit approval via --install-scripts flag or allowlist configuration.
Missing Controls
The primary failure was implicit trust. npm treated every package as equally trustworthy, allowing execution without user consent. This violated several security principles:
Least privilege: Install scripts had full access to the development environment without justification. A package that only needed to copy files could also access sensitive credentials.
Defense in depth: No secondary verification existed. If you installed a package, its scripts ran automatically.
Supply chain verification: npm provided no mechanism to review scripts before execution. Auditing install scripts across dependencies required manual inspection of package.json files.
Separation of duties: The same action (npm install) both downloaded code and executed commands, which should have been separate steps requiring separate approvals.
Relevant Standards
Several frameworks address this gap:
NIST 800-53, Control SA-10 (Developer Configuration Management) requires controlling changes during development and deployment. Automatic script execution violated this by allowing package maintainers to push code changes that executed immediately.
ISO/IEC 27001:2022, Annex A.8.31 (Separation of development, test and production environments) demands isolation between environments. Install scripts blur this boundary, potentially accessing production credentials.
PCI DSS, Requirement 6.3.2 states that vulnerabilities must be identified and addressed, including those in third-party components. You cannot address vulnerabilities in code that executes before review.
SOC 2, CC6.6 (Logical and Physical Access Controls) requires restricting access to authorized users. Automatic install scripts granted execution access to any package author.
The EU Cyber Resilience Act mandates secure development practices, and automatic execution of untrusted code doesn't meet that standard.
Action Items for Your Team
Before July: Prepare Your Environment
Map your install script dependencies. Run this in each repository:
npm ls --parseable | xargs -I {} sh -c 'cat {}/package.json 2>/dev/null' | jq -r 'select(.scripts.preinstall or .scripts.install or .scripts.postinstall) | .name'
Review each package using install scripts. Determine if the script is necessary or if another approach is possible.
Create an allowlist. In your .npmrc:
install-scripts=false
install-scripts-allowlist[]=node-gyp
install-scripts-allowlist[]=electron
Only add packages after verifying the necessity and reviewing the code.
Update your CI/CD pipelines. Use the --install-scripts flag only where needed, documenting each exception to create an audit trail.
After July: Maintain the New Posture
Treat install script approval as a security review. When a dependency update requires a new install script, conduct a code review. Understand what changed and why execution privileges are needed.
Monitor for workarounds. Developers might enable install scripts globally to avoid friction. Your CI logs should alert on --install-scripts usage outside approved contexts.
Cascade the principle. For internal packages, remove unnecessary install scripts. Use prepare scripts instead of postinstall scripts where possible.
Update your threat model. While the attack surface narrows, focus on compromised packages that don't need install scripts—malicious code in regular dependencies still executes when imported.
The Cultural Shift
This change prompts a critical question: how well do you know your dependencies? For years, npm install meant "trust everything." Now, it means "verify first."
Your allowlist becomes a living document of your dependency trust boundaries. Review it quarterly. Remove entries when packages eliminate install scripts. Challenge additions when developers request new exceptions.
Teams struggling with this change likely lacked dependency management policies. If npm's new default breaks your build, it's a signal: you've been running untrusted code without knowing it.
EU Cyber Resilience Act



