npm Install Scripts Opt-In RFC: Security Changes Explained
npm Security · May 2026

npm Install Scripts Opt-In RFC:
The End of npm's Most Dangerous Default

GitHub engineer Jamie Magee proposes making install scripts opt-in by default — the biggest npm security change in years. How it affects every JavaScript developer, what to do today, and a migration guide for package authors.

Oleg Maximov May 24, 2026 12 min read

What the RFC Proposes

On May 15, 2026, GitHub engineer Jamie Magee published an RFC proposing a fundamental change to how npm handles install scripts (preinstall, install, postinstall, prepare). The core idea is simple: instead of running dependency install scripts automatically, npm should require explicit opt-in from the developer.

The RFC was featured in JavaScript Weekly Issue 786 (May 19, 2026) and Node Weekly Issue 625 (May 21, 2026), where it was described as a long-overdue security improvement for the npm ecosystem. The proposal directly addresses a glaring asymmetry in the JavaScript package manager landscape: npm is the only major package manager that runs dependency install scripts by default.

Under the proposed change, when a developer runs npm install <package> and that package has install scripts, npm would either:

The exact UX mechanism is still under discussion, but the direction is clear: zero trust by default for install scripts.

Why This Matters: The Install Script Attack Surface

Install scripts are the primary attack vector in npm supply chain attacks. When you run npm install, any package in your dependency tree can execute arbitrary code through lifecycle scripts — before the package source is even fully installed. This is not a theoretical concern.

The Mini Shai-Hulud Case Study

The Mini Shai-Hulud worm (April–May 2026) compromised over 170 npm packages across TanStack, Mistral AI, UiPath, and other major ecosystems by injecting credential-stealing code through preinstall hooks. The attack worked because npm ran these scripts automatically — no user confirmation, no warning, no audit trail.

The malware used a preinstall hook to download and execute a Bun-based payload that stole GitHub tokens, npm credentials, cloud keys, and CI/CD secrets. It then used those credentials to publish compromised versions of other packages, creating a worm-like propagation chain. The entire attack vector depended on npm's default behavior of running scripts without question.

The Scale of the Problem

Install script attacks are not rare. Security researchers have documented hundreds of cases where malicious packages used postinstall or preinstall hooks to:

🔑 A 2024 study by the npm security team found that

over 60% of malicious npm packages used install scripts as their execution vector. Making scripts opt-in would have prevented the majority of all npm supply chain attacks in the past three years.

How Other Package Managers Handle This

npm is the outlier. Every other major package manager treats install scripts with suspicion. Here's how they compare:

Package Manager Runs Install Scripts by Default? Opt-In Mechanism
npm (current) Yes — always --ignore-scripts or .npmrc ignore-scripts=true
npm (proposed RFC) No — opt-in required allowedScripts config or --allow-scripts flag
pnpm No — blocked by default pnpm allow-scripts or allowedScripts in package.json
Yarn Classic Yes (legacy behavior) yarn install --ignore-scripts
Yarn Berry (v2+) Requires configuration dependenciesMeta with built: false
Deno No — scripts never run N/A — Deno downloads flat URLs, no lifecycle hooks
Bun Runs by default (npm-compatible) --ignore-scripts flag supported

The takeaway is clear: pnpm already has the exact mechanism npm is proposing, and it has not broken the ecosystem. Deno and Berry prove that a different model is viable. npm's proposed change brings it in line with the rest of the ecosystem — finally.

What Developers Should Do NOW

Even before the RFC lands (RFCs at npm historically take months to years to implement), there are concrete steps you should take today.

1. Set ignore-scripts=true in Your .npmrc

This is the single most impactful security measure you can take:

# ~/.npmrc or .npmrc in project root
ignore-scripts=true

With this setting, npm will download packages but not execute any install scripts. You can then selectively allow scripts for trusted packages:

# Run install normally for a specific package
npm install some-package --ignore-scripts=false

Or, use a more granular approach with npm query to inspect which packages have scripts before installing:

# Use npq (npm install qualifier) to audit before installing
npx npq install some-package

2. Audit Your Current Dependencies for Install Scripts

You may already have packages that rely on install scripts. Find them with:

# List all packages with lifecycle scripts
npx npm-query-lifecycle-scripts

# Or manually check package.json files
find node_modules -name "package.json" -exec grep -l '"postinstall"\|"preinstall"\|"prepare"' {} \;

Common legitimate uses of install scripts include:

3. Harden Your CI/CD Pipeline

In CI/CD, always use strict mode:

# CI/CD best practice — never run install scripts
npm ci --ignore-scripts

# Then build with explicit steps
npm run build

This ensures that no install script can execute in your build pipeline. If a package requires a script to function (e.g., a binary download), you should pre-download the binary or switch to a package that ships pre-built binaries.

Migration Guide for Package Authors

If you maintain an npm package that uses install scripts, the RFC affects you directly. When npm makes scripts opt-in, developers may not approve your scripts — and your package will break silently.

Audit Your Own Install Scripts

Check your package.json for any lifecycle scripts:

{
  "scripts": {
    "postinstall": "node postinstall.mjs",
    "preinstall": "node setup.mjs",
    "prepare": "husky"
  }
}

Ask yourself: does this script actually need to run on install? In most cases, the answer is no.

Migrate to Safer Alternatives

Here's a practical migration path for common install script use cases:

Current Pattern Better Alternative
postinstall for build steps Move to build or prepare (runs on publish, not install)
postinstall for native binary download Use optionalDependencies per platform with pre-built packages (e.g., @img/sharp-libvips-linux-x64)
postinstall for code generation Require explicit npm run generate or use prepublishOnly for package authors
postinstall for setup messages Replace with a README.md section or a setup script documented in the README
prepare for git hooks (husky) Husky v9+ already moved to husky init — explicit, not automatic
preinstall for compatibility checks Use engines field in package.json with engine-strict config

Add an allowedScripts or Documentation Path

If your package legitimately needs an install script (and after audit, you're certain), document it clearly and provide an allowedScripts configuration snippet that developers can copy. For example:

# .npmrc — add this to your project root
allowedScripts[my-package]=true

This makes the trust decision transparent and reproducible — the same way you'd document a build step.

The Broader Shift: npm Security Improvements in 2026

The install scripts RFC is not happening in isolation. 2026 has been a transformative year for npm security. The ecosystem is undergoing the most significant hardening in its history.

npm Staged Publishing (npm 11.15.0)

Announced in the same week as the RFC, npm's new staged publishing model provides a review period before packages go live. This prevents attackers from publishing malicious versions that would be immediately available to millions of developers — a key mitigation for the "publish and exploit" pattern used in supply chain attacks.

npm 12.0 Prerelease

A prerelease of npm 12.0 has been published, signaling major architectural changes. While the exact changelog is emerging, the version bump from 11.x indicates significant breaking changes — likely including the install scripts RFC or its early implementation.

Script Security GA (February 2026)

npm's script security feature, which provides warnings about packages with lifecycle scripts during installation, graduated to General Availability in February 2026. This was the first step in the current hardening trajectory. The RFC is the logical next step: from warning about scripts to blocking them by default.

2FA Enforcement for High-Impact Packages

npm now enforces two-factor authentication for maintainers of high-download packages, closing the account takeover vector that has been used in several supply chain attacks. This complements the install scripts RFC by addressing a different part of the attack surface: who can publish, rather than what runs on install.

A Practical Guide: Auditing Your Dependencies for Install Script Usage

Here's a step-by-step workflow to audit your project today, regardless of the RFC's status:

  1. Check your current .npmrc — Run npm config ls to see if ignore-scripts is already set. If not, add it.
  2. List packages with install scripts — Use npx npm-query-lifecycle-scripts to see every package in your tree that defines lifecycle scripts.
  3. Evaluate each script — For every package with a script, check its source code and documentation. Ask: Is this script necessary? Is it documented? Can it be replaced?
  4. Test with scripts disabled — Set ignore-scripts=true temporarily and run your full test suite. Any failures reveal packages that genuinely need scripts. Document these exceptions.
  5. Create an allowed-scripts policy — For packages that legitimately need scripts, create a documented allowlist that your team can review and maintain.
  6. Add CI checks — Add a CI step that warns when new packages with install scripts are added to the dependency tree, using tools like socket.dev or snyk.
  7. Stay informed — Follow the RFC discussion at github.com/npm/rfcs. The discussion thread includes valuable input from maintainers of packages that depend on install scripts.

🔧 Quick Setup: The 30-Second Security Upgrade

If you do nothing else today, add this to your ~/.npmrc: ignore-scripts=true. Then, when a package you trust needs scripts, grant permission explicitly with npm install --ignore-scripts=false. This single change blocks the attack vector used by Mini Shai-Hulud and most other npm supply chain attacks.

For secure web application development, get in touch

FAQ

What is the npm install scripts opt-in RFC?
Proposed by GitHub engineer Jamie Magee and featured in JavaScript Weekly Issue 786 (May 19, 2026), the RFC proposes that npm change its default behavior so that install scripts (postinstall, preinstall, prepare) require explicit user opt-in rather than running automatically. npm is currently the only major package manager that runs dependency install scripts by default.
Why is npm making install scripts opt-in?
Install scripts have become the primary attack vector for npm supply chain attacks. The Mini Shai-Hulud worm (May 2026) compromised 170+ packages by injecting malicious code through preinstall hooks. Other package managers like pnpm, Yarn, Bun, and Deno either block install scripts by default or require explicit approval. Making scripts opt-in closes the most dangerous attack surface in the npm ecosystem.
How will the opt-in RFC affect existing npm packages?
Packages that rely on install scripts for legitimate purposes — build steps, native binary compilation, postinstall cleanup — will need to be explicitly trusted by developers. Package authors should migrate to lifecycle hooks that don't run on install (like build or prepublishOnly), use platform-specific packages, or leverage the install script only for critical setup with clear documentation. A transition period with warnings before breaking changes is expected.
How do other package managers handle install scripts?
pnpm blocks install scripts by default — packages must be in the allowedScripts configuration to run them. Yarn (classic) runs scripts but Yarn Berry (v2+) requires configuration. Deno and Bun take a fundamentally different approach: Deno downloads dependencies as flat URLs without running scripts, and Bun requires explicit permission for lifecycle scripts. npm is the only major package manager that runs install scripts by default, making it the outlier in ecosystem security.
What should developers do before the RFC lands?
Start setting ignore-scripts=true in your .npmrc today: it's a security best practice regardless of the RFC outcome. Audit your dependencies for install script usage with npm query or the npx npm-query-lifecycle-scripts tool. For CI/CD, always use npm ci with --ignore-scripts, then selectively allow scripts only for trusted packages. Package authors should start migrating away from install scripts to safer alternatives.
How does this relate to the Mini Shai-Hulud npm attack?
The Mini Shai-Hulud worm (April–May 2026) exploited npm's default install script execution to compromise 170+ packages. It injected credential-stealing code through preinstall hooks that ran automatically on npm install, then used stolen tokens to publish malicious versions of other packages. The opt-in RFC is a direct response to attacks like these — closing the systemic vulnerability rather than responding to individual incidents. See our complete analysis of the Mini Shai-Hulud npm supply chain attack.
What alternatives to postinstall scripts exist?
For build steps: use build scripts and npm run build. For native binaries: package pre-built binaries per platform (os/optionalDependencies pattern). For code generation: move to prepublishOnly which only runs on npm publish. For postinstall notifications: consider a README note instead. Many packages that used postinstall for compilation (like node-sass) have already moved to pre-built binaries. The general principle: anything that must run when the package is installed should be minimized, documented, and justified. For a deeper dive into supply chain security, see our analysis of the Grafana GitHub token breach and the TeamPCP VS Code extension attack.

Security Starts with Awareness

The npm install scripts opt-in RFC represents a fundamental shift in how the JavaScript ecosystem approaches security. It acknowledges that the default behavior that made npm successful — install scripts running automatically — has become its greatest weakness.

As developers, we've been trusting install scripts by default because there was no alternative. The RFC changes that. It moves the ecosystem from "trust by default, audit by exception" to "audit by default, trust by exception". That's the right direction.

If you're building a web application and want a developer who takes dependency security seriously — not as an afterthought but as a built-in practice — reach out to me. I'm a full-stack developer with 20+ years of experience, and I build every project with --ignore-scripts, pinned dependencies, lockfile integrity checks, and automated security scanning from day one.

Contact

Let's build something secure

Have a project in mind? I'll help you choose a secure, modern tech stack and build it right. Free initial consultation.