npm v12 Will Stop Running Install Scripts. We Audited Our Repos to See What Actually Breaks
On June 9, GitHub announced the breaking changes coming in npm v12, estimated to ship in July 2026. The headline change: npm install will no longer execute preinstall, install, or postinstall scripts from your dependencies unless you have explicitly approved them. Not as an option you can turn on. As the default, for everyone.
If you have followed the npm worm coverage on this site over the past months (TanStack, PyTorch Lightning's mini Shai-Hulud, axios, the AntV wave), you already know why. Every one of those campaigns used the same beachhead: a script that runs automatically, with your credentials, the moment you install a package. GitHub calls lifecycle scripts the single largest code-execution surface in the npm ecosystem, and after the June 1 Red Hat compromise shipped credential stealers with valid SLSA provenance, the argument for keeping that surface open by default ran out.
So instead of writing about the policy, we did the thing you should do this week: upgraded npm and ran the new audit tooling against our own production repositories. Here is what v12 will actually do to a real Next.js application and a couple of TypeScript tooling repos, including the part where much less breaks than the audit output suggests.
What changes, exactly
Three defaults flip in v12:
- Dependency lifecycle scripts stop running.
preinstall,install, andpostinstallfrom dependencies are skipped unless the package is on your project's allowlist. This includes implicit builds: a package with abinding.gypand no declared install script still gets blocked, because npm runs an implicitnode-gyp rebuildfor it.preparescripts from git, file, and link dependencies are covered too. - Git dependencies need
--allow-git. Direct or transitive git dependencies stop resolving without the flag. This closes an ugly hole: a git dependency's.npmrccould override which git executable npm invokes, which meant code execution even under--ignore-scripts. - Remote URL dependencies need
--allow-remote. Tarballs pulled from HTTPS URLs stop resolving without explicit opt-in.file:and directory dependencies keep their current behavior.
Your own project's scripts still run. If your root package.json has a postinstall that runs patch-package, or a prepare that installs husky hooks, nothing changes for you. The allowlist is about code arriving from the registry, and it lives in your package.json, which means script approvals show up in pull requests and get reviewed like any other change.
All of this is already available as warnings in npm 11.16.0 and later, which is what makes the audit possible before July.
The audit: 65 warnings, 4 that matter
We ran npm approve-scripts --allow-scripts-pending (npm 11.17.0) against this site, a production Next.js application with a fairly typical dependency tree. The output flags 65 packages with lifecycle scripts not yet covered by an allowlist. Out of context, that number reads like a migration project.
It is not, and the breakdown shows why:
Sixty-one of the sixty-five are prepare scripts: husky hook installation, npm run build, the usual library housekeeping. prepare only executes when you install a package from git, a local file, or a link, never from a normal registry install. Unless you are pinning one of those packages to a git ref, these entries are inert. The audit lists them because it cannot know you will not switch a dependency to a git URL tomorrow, but for triage purposes you can put them at the bottom of the pile.
That leaves four entries that run today on every clean install of this repo: sharp (image processing, used by Next.js image optimization), esbuild twice at different versions, and unrs-resolver. All native code. These are the ones that could break a build in July.
Two smaller repos made the point even more cleanly: our open source benchmark harness and its dashboard each flagged exactly one package. Both times it was esbuild.
The plot twist: we denied them and nothing broke
Here is the part worth the price of admission. We installed sharp and esbuild into a clean project with scripts disabled, then exercised both:
sharpcreated and encoded an image without itsinstallscript ever running.esbuildtransformed TypeScript without itspostinstall.
No failures, no missing binaries. The reason: both packages migrated their native binary distribution to optionalDependencies (@img/sharp-linux-arm64, @esbuild/linux-arm64, and their platform siblings), which are plain packages that install without any script execution. The lifecycle scripts that the audit flags are validation and fallback paths for platforms without a prebuilt binary, not the primary delivery mechanism.
This is the quiet story behind npm v12: the ecosystem's most depended-on native packages already left install scripts behind, in large part because the worm era made every install-time hook a liability. The default flip in July is less a demolition and more the locking of a door most serious packages already stopped using.
What will actually break
That does not make the change free. The breakage concentrates in specific places, and they are worth checking deliberately:
- Long-tail native modules built with node-gyp. Anything that compiles C++ on install and has not moved to prebuilt binaries stops working until allowlisted, including packages with only an implicit
binding.gypbuild. Older database drivers, hardware bindings, and that one image library from 2019 live here. - Downloaders. Packages whose
postinstallfetches something big: Puppeteer and Playwright pulling browsers, Cypress pulling its binary. Denied scripts mean the tool installs but fails at runtime with a missing executable, which is a worse failure mode than failing at install. - Git and URL dependencies. Any
"some-fork": "github:org/repo#branch"in your tree needs--allow-gitin every CI job and Dockerfile that installs it. Private tarball URLs need--allow-remote. These fail loudly at resolve time, so you will notice, but you will notice in the middle of an incident if your first v12 install happens during one. - CI images that float npm versions. If your Dockerfile does
npm install -g npm@latestor your CI uses anode:lateststyle tag, v12 arrives on its schedule, not yours.
The checklist
The whole audit took us under fifteen minutes for three repos. Doing it now means July is a non-event:
- Upgrade to npm 11.16.0 or later somewhere representative (a dev machine is fine, CI is better).
- Run
npm approve-scripts --allow-scripts-pendingin each repo. Ignore theprepareentries from registry packages on the first pass. - For each real
install/postinstallentry, decide: approve it withnpm approve-scripts <pkg>, or test whether the package works without it (as with sharp and esbuild above, the answer is increasingly yes) and deny it withnpm deny-scripts <pkg>. - Commit the resulting allowlist in
package.json. From now on, a new dependency wanting script execution shows up in code review instead of executing silently. - Grep your Dockerfiles and CI for git and URL dependencies, and add the flags where genuinely needed.
- Pin your npm major version in CI images, and schedule the v12 upgrade like any other dependency upgrade instead of receiving it as a surprise.
One honest caveat: July 2026 is GitHub's estimate, and details of partially shipped behavior have moved before (the git restriction landed in 11.10, remote URLs in 11.15, the full allowlist tooling in 11.16). The direction is not in question, though. Install-time code execution from the registry is ending as a default, three years of worms made the case, and the audit that tells you whether you care takes less time than reading this post did.
We earn commissions when you shop through the links below.
DigitalOcean
Cloud infrastructure for developers
Simple, reliable cloud computing designed for developers
DevDojo
Developer community & tools
Join a community of developers sharing knowledge and tools
SMTPfast
Developer-first email API
Send transactional and marketing email through a clean REST API. Detailed logs, webhooks, and embeddable signup forms in one dashboard.
QuizAPI
Developer-first quiz platform
Build, generate, and embed quizzes with a powerful REST API. AI-powered question generation and live multiplayer.
Want to support DevOps Daily and reach thousands of developers?
Become a SponsorFound an issue?
Related Posts
Also worth your time on this topic
The Axios Supply Chain Attack: What DevOps Teams Need to Know
A compromised npm maintainer account led to malicious axios versions deploying a RAT across macOS, Windows, and Linux. Here is what happened, how to check if you are affected, and how to prevent this in your pipeline.
Complete Web Server Automation with Ansible
Build a comprehensive Ansible playbook to automate web server deployment, configuration, and security hardening across multiple environments.
75 minutes
AWS Security Checklist
Essential security configuration checklist for AWS cloud environments.
45-60 minutes