Skip to content

Plans for npm 12 #1161

Closed
Closed

Description

@JamieMagee

The npm team is working on npm 12, which is estimated to release in July 2026. I'm opening this issue to discuss the planned breaking changes and to work out how we land them in Node.js, following the same process used for npm 9 (#778) and npm 10 (#884).

npm 12 is a security-focused release. Every breaking change turns an npm install behaviour that runs automatically today into one you opt into. The reason I'm filing this early is that a lot of users have asked for these protections to reach the active release lines, specifically Node 24 and Node 26, rather than waiting for the next major to age into LTS. I'd like the release team's input on whether that's possible.

All of these changes are already available behind warnings in npm 11.16.0 and later, so people can test against them before the major lands. They were announced on the GitHub blog on 9 June 2026, and there is an open community discussion for feedback.

Breaking changes

We plan to follow the guidelines on integrating npm with Node, and we consider the changes below to fall within them.

Install scripts are opt-in (allowScripts defaults to off)

npm install will no longer run preinstall, install, or postinstall scripts from dependencies unless you have allowed them in your project. This includes native node-gyp builds: a package that ships a binding.gyp with no explicit install script is still blocked, because npm runs an implicit node-gyp rebuild for it. prepare scripts from git, file, and link dependencies are blocked the same way.

You allow scripts per package through a new allowScripts field in package.json, managed with two new commands, npm approve-scripts and npm deny-scripts. This is RFC 54. It brings npm in line with pnpm, Yarn, Bun, and Deno, which all block dependency install scripts by default already.

Git dependencies are opt-in (--allow-git defaults to none)

npm install will no longer resolve git dependencies, direct or transitive, unless you allow them with --allow-git. This closes a code-execution path where a git dependency's .npmrc could override the git executable, which ran even with --ignore-scripts. The change was announced on 18 February 2026 and is available in npm 11.10.0 and later.

Remote URL dependencies are opt-in (--allow-remote defaults to none)

npm install will no longer resolve dependencies from remote URLs, such as https tarballs, direct or transitive, unless you allow them with --allow-remote. This is available in npm 11.15.0 and later. The related --allow-file and --allow-directory flags keep their current defaults in npm 12.

Why we'd like these in Node 24 and 26

This is the part I most want the release team's input on.

All three defaults exist to cut off code that runs during npm install, before any application code is imported.The supply-chain attacks of the last two years leaned on exactly this. event-stream, the Lazarus campaigns, the chalk and debug compromise, the Shai-Hulud worm, and the Axios hijack in March all used an install script or install-time resolution as the entry point.

Node's LTS policy already allows a semver-major change to ship as a semver-minor when the reason is security. npm took this path in npm 9 for the unscoped _auth change (see the discussion in #778), and backported it rather than holding it for the newest line. The npm 12 defaults are the same category of change. So I think there's a reasonable case for getting them onto the active lines, where most users actually are, instead of only the next major.

I know that shipping breaking changes into LTS has been contentious in past npm updates (#884), which is why I want to raise this now and work through the concerns together rather than at release time.

Testing

We'll hold npm 12 to the integrating-with-node guidelines: no new failures in Node's own test suite, no new failures installing or testing the citgm package set, and no backwards-incompatible changes to existing package-lock.json files.

As with npm 10, we'll run our node-integration workflow in GitHub Actions against every npm 12 prerelease so regressions show up early, and CI runs on every PR the npm team opens.

Timeline

Prereleases are already underway. npm@12.0.0-pre.0 shipped on 20 May 2026, and the next prerelease (12.0.0-pre.1) is pending in the release PR npm/cli#9387. The goal is to make npm 12 testable inside Node as early as possible: CI-only PRs to main during the prereleases, a review-ready PR once npm 12 is stable, then backport PRs for the Node 26 and Node 24 release lines.

# Task Status / target
1 First prerelease (npm@12.0.0-pre.0) Done, 20 May 2026
2 Further prereleases (12.0.0-pre.1 and later) In progress (pre.1 pending in npm/cli#9387)
3 CI-only PR(s) to Node.js main During prereleases
4 Major release (npm@12.0.0) Targeting July 2026
5 Open review-ready PR to Node.js main With major release
6 Land npm 12 on Node.js main After review
7 Promote npm@12.0.0 to latest July 2026
8 Open PR to backport to Node.js 26 After landing on main
9 Open PR to backport to Node.js 24 After landing on main
10 Release npm 12 in Node.js 26 Tentative
11 Release npm 12 in Node.js 24 Tentative

Dates are tentative and depend on how prerelease testing goes.

Links

Activity

  1. ljharb commented on Jun 11, 2026

    @ljharb
    SponsorMember

    I think it's definitely worth it for 26, since it's a pretty new major, it's not LTS yet, and anyone impacted can add

    allow-scripts=true
    allow-git=all
    allow-remote=all
    

    to .npmrc or ~/.npmrc to unblock themselves (although hopefully they wouldn't want to).

    For 24 is a tougher sell, but I'd love to hear releasers' thoughts on it.

  2. richardlau commented on Jun 12, 2026

    @richardlau
    Member

    My opinion is that this should only land in Node.js 26 and 24 as Node.js security updates. There is a clear Node.js release policy (as mentioned) for this, and there would be more opportunity to communicate the change.

    Since there would be options to opt back into the old behaviour, I am in favour of releasing npm 12 in Node.js 24 and 26 in a security release.

  3. wesleytodd commented on Jun 15, 2026

    @wesleytodd
    Member

    Landing this on 24/26 breaks the guidance here if you treat it in spirit instead of as written AFAICT:

    When a release is published, we will use citgm (or some derivative) to download the latest published version of each package and run npm install followed by npm ls to verify we have generated a valid package tree.

    Specifically this would mean that a package is installed and ls's just fine but any binary dep was never built and thus the same install prior to npm@12 would be broken despite passing these tests. IMO the spirit of that guideline implies that the install is functional despite not saying that. I can open a PR to fix that gap if necessary, but want to discuss here to see if there is a consensus on this first.

    Security release or not, this release contains changes with very widespread impact. Saying apps can set .npmrc configs does not mitigate the impact to users who may not understand what these changes even do breaking their builds. As discussed in slack the only way these changes can be done in a way that unimpeachably semver compatible would be if node also shipped a config override in it's default installers. This would scope the breaking change to just folks using non-standard installers (of which I happen to be one) and thus maybe meets the spirit of the policy but still is technically breaking for this smaller set of users.

    So, while I am very happy with the direction for this npm major I am opposed to this shipping in any existing node.js major lines. Folks can and are already using the configuration features in their apps, but the vast majority of folks rely on the default experience being stable (even at the cost of poor security or hygiene) and that is on the top of the projects technical values.

  4. jenseng commented on Jun 15, 2026

    @jenseng

    This is a great change security-wise. That said, I have serious reservations about it landing in an already released major -- particularly v24 given its broad usage.

    For example, In CI systems like GitHub Actions, it's extremely common to do something like:

    - uses: actions/setup-node@v6
      with:
        node-version: 24 # or `current`, or `lts/*`, etc.
    - run: npm ci
    - run: npm run test

    If your tests rely on native deps, your jobs will inexplicably start failing as soon as node 24 ships with npm 12. While you can pin back to 24.16.0, or add the necessary entries to your .npmrc, this will not be obvious. I anticipate this causing a large amount of pain and churn for developers and platform providers alike.

  5. targos commented on Jun 16, 2026

    @targos
    Member

    I don't know how that has been implemented in the end, but the RFC says that the default behaviour would be to print clear warnings to the console about the packages that have install scripts and what to do to allow them. Users wouldn't necessarily be completely lost (I know, many people don't pay attention to warnings).

  6. MikeMcC399 commented on Jun 16, 2026

    @MikeMcC399
  7. wesleytodd commented on Jun 16, 2026

    @wesleytodd
    Member

    I think it's definitely worth it for 26, since it's a pretty new major, it's not LTS yet

    At this time I would suggest allowing npm 12 into the Node.js 26 release line once it is released and well tested

    Why would the same concern and decision logic not apply to Node 26? Despite not being LTS yet it is not usually acceptable to land breaking changes in the current phase either.

    My opinion is that this should only land in Node.js 26 and 24 as Node.js security updates.

    Is anyone taking a strong stance that this is a security release that justifies a mid-major breaking change release? I understand that it could be done, but I would argue that because the feature is usable on npm@11 there is no incentive to rush a change that could have many negative effects like what @Waldenesque points out and what @MikeMcC399 uses to justify this in 24.

    Again, I am really happy to push forward on driving adoption of the feature and npm@12. I just don't think folks are presenting a case that justifes breaking the semver contract here. I think rushing this change will not serve to push adoption of the new feature, it is more likely to strand some segment of users and annoy some other segment.

  8. richardlau commented on Jun 16, 2026

    @richardlau
    Member

    I think it's definitely worth it for 26, since it's a pretty new major, it's not LTS yet

    At this time I would suggest allowing npm 12 into the Node.js 26 release line once it is released and well tested

    Why would the same concern and decision logic not apply to Node 26? Despite not being LTS yet it is not usually acceptable to land breaking changes in the current phase either.

    +1 Node.js 26 is already released and follows semver. The fact that it is not yet considered Long Term Support is not an excuse to ignore semver outside of the security provision.

    My opinion is that this should only land in Node.js 26 and 24 as Node.js security updates.

    Is anyone taking a strong stance that this is a security release that justifies a mid-major breaking change release?

    To clarify my own earlier comment I'm okay either way, but if we (as a whole) decide that it is worth making the breaking change, then for me it has to be done under the existing provision for security fixes -- even on Node.js 26.

    I'm not too keen on the idea of including npm 12 in 26 and/or 24 but Node.js overriding the defaults -- I think we'd be better off sticking with npm 11 in that scenario.

  9. JamieMagee commented on Jun 22, 2026

    @JamieMagee
    Author

    Thanks everyone, this is the conversation I was hoping for.

    @richardlau and @wesleytodd you make a fair point that "26 is new and not LTS yet" isn't the right framing. 26 follows semver too. If these defaults land in 24 or 26, the only honest justification is the security provision in the release policy, and it has to clear that bar for both or neither.

    The policy allows an npm semver major to land as a node semver minor when it's a critical security fix, as long as there's a revert option. I believe all three npm 12 breaking changes fit that criteria. Each one closes a path that runs attacker-controlled code during npm install, before any application code is imported:

    • Install scripts closes preinstall/install/postinstall and the implicit node-gyp rebuild. This is the vector behind event-stream, the Lazarus campaigns, the chalk/debug compromise, the Shai-Hulud worm, and the Axios hijack.
    • Git dependencies (--allow-git=none) closes a case where a transitive git dep's .npmrc could override the git binary and run even under --ignore-scripts.
    • Remote URL dependencies (--allow-remote=none) closes install-time resolution of arbitrary https tarballs.

    Every one of these is an entry point that real supply-chain attacks have used in the last two years.

    On the revert requirement: it's already handled. Anyone affected can set allow-scripts, allow-git, and allow-remote in .npmrc or ~/.npmrc, or approve individual packages with npm approve-scripts. The policy asks for a revert option, and npm 12 ships with one at the project, package, and global level.

    The precedent is #778. npm 9 changed unscoped _auth handling for security, landed as a node semver minor, and was backported to the existing releases rather than held for the next major. Holding npm 12 for the next major to age into LTS would put the protection everywhere except where most users actually are.

  10. theodorejb commented on Jun 22, 2026

    @theodorejb

    As a longtime Node and npm user I really hope these fixes can make it into Node 24 (or Node 26 at the very latest). Having to wait more than a year before these regularly exploited security loopholes can be closed in an LTS release would be a terrible outcome.

  11. wesleytodd commented on Jun 23, 2026

    @wesleytodd
    Member

    The policy allows an npm semver major to land as a node semver minor when it's a critical security fix

    While I agree on the fact these close security gaps in npm (I have been working with the npm team for years now on these exact topics, you and I haven't met yet, but happy to have a new face to continue that tradition with), if it was a "critical" security fix it would have been done years ago. Sorry you are strapped with this history, but the fact is that it was not deemed critical in that time for reasons. We could discuss if they are good reasons or not, but I don't think that is valuable here today.

    On the revert requirement:

    I agree this is met in the letter of the policy, but I think the spirit of the policy is that releasers should judge the impact of the changes to determine a go/no-go on shipping it this way. My case here would be that it has too high of an impact if changed to be worth the improvements that come along with it:

    1. users can already use it with v11
    2. users can upgrade to v12 in their workflows/deployments
    3. changing the default will cause many unaware users to simply allow all scripts rather than going through the poor UX of setting individual allow rules (a solvable problem, but not solved yet)
    4. breaking builds is HIGHLY user visible. Many security breaking changes that follow this policy are much less visible, so this change should be held to a higher bar.

    The precedent is #778. npm 9 changed unscoped _auth handling for security, landed as a node semver minor, and was backported to the existing releases rather than held for the next major.

    This example explicitly fits in with that last point. FWIW, that change also broke some of our tooling and builds but it was manageable because the scope of impact was small. This change fundamentally breaks every build it touches. Hence my increased concern.

    As a longtime Node and npm user I really hope these fixes can make it into Node 24 (or Node 26 at the very latest). Having to wait more than a year before these regularly exploited security loopholes can be closed in an LTS release would be a terrible outcome.

    Hey @theodorejb! Thanks for helping give some voice to the user impact of the ongoing security issues surrounding of these decisions. You are absolutely right that it is bad we have been in this state for so long, and waiting longer is not at all desirable. I would strongly suggest you work on your workflows to upgrade npm independently from Node.js releases. It is a helpful feature to have in many cases, and one we use to address issues like this all the time across our fleet.

    That said, I think the sentiment here is more for users who cannot or do not know how to do this. Which is likely also the group of folks who would fit into point 3 above (not yourself). For them, we need to consider what folks usually do when their build breaks, for an example I will use peer dependencies. When a build breaks because of a peer dep conflict, a large percentage of users set --legacy-peer-deps and move on. Not aware, or ignoring, the fact that npm can resolve the peer deps if they are declared correctly.

    The same applies here, but the impact of that choice is a significantly worse security outcome for both them and the ecosystem. Once allow scripts is set to all for that project, the chance of it being revisited in a timely manner is quite low. From a security posture, we are only as strong as our weakest link and should act to protect that weakest link first. My suggestion to ship this with Node 27 is specifically for this subset of the ecosytem which I consider our "weakest link". And specifically I believe it is a more "terrible outcome" than informed users like all of us here upgrading our projects and setting these configurations judiciously.

  12. wesleytodd commented on Jun 23, 2026

    @wesleytodd
    Member

    On a separate note: which group is delegated this decision, is it the releasers group? This decision is an important one and I would like to help bring context/nuance to the decision. If there is an upcoming meeting I can attend I would love to. If there is no meeting time to discuss this in real time, no problem, just want to make sure that I don't miss something on this discussion due to being unable to maintain my GH notifications.

  13. richardlau commented on Jun 23, 2026

    @richardlau
    Member

    Content of releases is delegated to the Release Working Group.
    Security evaluations are the security team (or possibly the separate Security WG as it is more an ecosystem question than core Node.js issue).
    This hasn't been tagged for an agenda (yet) so is not scheduled to be discussed in a meeting at present.

  14. JamieMagee commented on Jun 23, 2026

    @JamieMagee
    Author

    Thanks @wesleytodd, and good to meet you 👋

    Quick status first: I've opened the first CI-only PR against main, nodejs/node#64096. It's marked not for merge and just runs npm 12.0.0-pre.1 through Node's CI.

    On "if it were critical it would have been done years ago": the risk was always real, what was missing was a fix that didn't break half the ecosystem. RFC 54 was first written in 2021, and the blocker then was native addons. Too many packages compiled through node-gyp at install time, so turning scripts off by default would have broken a large share of installs. Since then the ecosystem moved to prebuilt platform binaries shipped through optionalDependencies. esbuild, sharp, SWC, and Rollup all did it, and Node-API gives the ABI stability that makes prebuilds work without recompiling. The packages that still need an install script are a small and shrinking minority now. So the gap staying open in 2021 says more about what was feasible then than how serious it is, and I'd rather not treat "we lived with it for years" as a reason to keep living with it.

    On 24 and 26: let me adjust the framing. The security-provision bar still has to be cleared the same way for either line, I'm not backing off that. But on timing I don't think they need to move together. 26 first, after it's been through Node's CI and citgm, then 24 later as its own decision once we can see how 26 landed.

    Last, on process: @richardlau Can we get it tagged for a Release WG agenda item and talk it through? I can be there if needed.

  15. 20 remaining items

  16. MikeMcC399 commented on Jul 29, 2026

    @MikeMcC399

    @ljharb

    I think it's definitely worth it for 26, since it's a pretty new major, it's not LTS yet, and anyone impacted can add

    allow-scripts=true
    allow-git=all
    allow-remote=all
    

    to .npmrc or ~/.npmrc to unblock themselves (although hopefully they wouldn't want to).

    For 24 is a tougher sell, but I'd love to hear releasers' thoughts on it.

    Could you check allow-scripts=true? I don't think that is correct and it doesn't follow what https://docs.npmjs.com/cli/v12/using-npm/config#allow-scripts says.

  17. ljharb commented on Jul 29, 2026

    @ljharb
    SponsorMember

    @MikeMcC399 have you tried it? i'm pretty confident.

  18. MikeMcC399 commented on Jul 29, 2026

    @MikeMcC399

    @ljharb

    Yes I tried it and it didn't work for me.

    Steps to reproduce

    Ubuntu 26.04, Node.js 26.5.0 (bundled npm 11.17.0)

    npm install npm@12.0.1 -g
    cd $(mktemp -d)
    npm config set allow-scripts=true --location=project
    npm config list
    rm -rf ~/.cache/Cypress
    npm install cypress
    npx cypress verify
    npm warn install-scripts 1 package had install scripts blocked because they are not covered by allowScripts:
    npm warn install-scripts   cypress@15.19.0 (postinstall: node dist/index.js --exec install)
    npm warn install-scripts
    npm warn install-scripts Run `npm install-scripts ls` to review, or `npm install-scripts approve <pkg>` to allow.
    $ npx cypress verify
    npm notice run npx
    npm notice run 'cypress' verify
    No version of Cypress is installed in: /home/mike/.cache/Cypress/15.19.0/Cypress
    
    Please reinstall Cypress by running: cypress install

    Remediate with:

    npm install-scripts approve cypress
    npm rebuild cypress
    npx cypress verify
    Approved cypress:
      added cypress@15.19.0
    npm warn install-scripts .npmrc allow-scripts setting is being ignored because package.json declares its own allowScripts field
    rebuilt dependencies successfully
    npm notice run npx
    npm notice run 'cypress' verify
    
    ✔  Verified Cypress! /home/mike/.cache/Cypress/15.19.0/Cypress

    Or downgrade with:

    npm install npm@11 -g
  19. MikeMcC399 commented on Aug 1, 2026

    @MikeMcC399
  20. MikeMcC399 commented on Aug 1, 2026

    @MikeMcC399
  21. richardlau commented on Aug 13, 2026

    @richardlau
    Member

    The Release WG has decided not to land npm 12 on Node.js 26, 24 or 22.

  22. reggi commented on Aug 26, 2026

    @reggi

    I work at GitHub on npm. I find it unfortunate that we aren't able to get npm@12 into node v26 from this decision here, if there's anyway to appeal that decision with a possible allow-scripts related config update I'm very open to discussing what it would take to get it in node v26. Apr 29, 2029 is a long time to have people continue to run on npm@v11.

  23. theodorejb commented on Aug 26, 2026

    @theodorejb

    I also wish that npm 12 could be included in Node 26. Otherwise a lot more people will end up compromised by postinstall scripts running by default for any dependency.

  24. manzoorwanijk commented on Sep 22, 2026

    @manzoorwanijk

    It's such a pity that npm was forced to revert the error on unknown .npmrc configs (npm/cli#9729) to allow it to be considered for Node v26, and then it ended up not being included in the version. 🤦

  25. MikeMcC399 commented on Sep 22, 2026

    @MikeMcC399

    It's such a pity that npm was forced to revert the error on unknown .npmrc configs (npm/cli#9729) to allow it to be considered for Node v26, and then it ended up not being included in the version. 🤦

    This already has an impact on Renovate lock file maintenance, which uses the latest version of npm (currently 12.0.2). If this change hadn't been made, then Renovate would already be broken. This is independent of any bundling in Node.js.

  26. MikeMcC399 commented on Sep 22, 2026

    @MikeMcC399

    I've requested in npm/cli#9997 for the npm team to submit npm@12 in time for Node.js 27. I don't believe there is any realistic chance of reaching a consensus to revert the decision not to backport npm@12 to Node.js 26. The release of npm@12 was too late for Node.js 26, and there are too many breaking changes in npm@12, as listed on https://github.com/npm/cli/releases/tag/v12.0.0.

    Users need to make their own decision about when to upgrade, and not be forced into unexpected breaking changes. npm already allows optionally upgrading in-place - see https://docs.npmjs.com/try-the-latest-stable-version-of-npm

  27. manzoorwanijk commented on Sep 22, 2026

    @manzoorwanijk

    This already has an impact on Renovate lock file maintenance, which uses the latest version of npm (currently 12.0.2). If this change hadn't been made, then Renovate would already be broken. This is independent of any bundling in Node.js.

    That is the whole point of breaking changes when it comes to security. The ecosystem would have adapted to the new security standard, but the main push for a revert was made in this thread, without which the WG here wouldn't entertain it for being considered for v26.

  28. simhnna commented on Oct 15, 2026

    @simhnna

    I'm also sad about it not making 26, but I guess I can live with that.
    I can set CI to use npm ci --strict-allow-scripts and add strict-allow-scripts=true in all project .npmrc files. I personally would add it to my global .npmrc so every project I checkout gets the treatment.
    The only difference is that it actively blocks install until every dependency is either allowed or denied. Maybe npm@11 could ship another option that behaves like npm@12 in that it doesn't block everything but just the undecided/denied packages.

  29. MikeMcC399 commented on Oct 15, 2026

    @MikeMcC399

    Node.js 27 (Alpha) is planned for release on 2026-10-28, and I would expect it to include npm@12.

    I already tried it out by installing a Node.js nightly build with with n Node.js version manager installed.

    $ n nightly
      installing : nightly-v27.0.0-nightly2026101512ce81920a
           mkdir : /home/mike/n/n/versions/nightly/27.0.0-nightly2026101512ce81920a
           fetch : https://nodejs.org/download/nightly/v27.0.0-nightly2026101512ce81920a/node-v27.0.0-nightly2026101512ce81920a-linux-x64.tar.xz
         copying : nightly/27.0.0-nightly2026101512ce81920a
    npm warn cli npm v12.1.0 does not support Node.js v27.0.0-nightly2026101512ce81920a. This version of npm supports the following node versions: `^22.22.2 || ^24.15.0 || >=26.0.0`. You can find the latest version at https://nodejs.org/.
       installed : v27.0.0-nightly2026101512ce81920a (with npm 12.1.0)

    Nightly builds are only for advance testing, not to be relied on, and definitely not for production usage!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions