Repository navigation
Description
Summary
With min-release-age now available (#8965), there is a common workflow that remains unsupported: applying a strict release age policy for third-party dependencies while allowing immediate updates for internally maintained packages.
This was originally proposed as part of #8825 (minimum-release-age-exclude), but was not carried forward into #8965, which focused on solving one problem at a time.
Motivation
As @yeikel noted in #8965 (comment):
From the diff, it seems the decision was made not to allow excluding packages. That's fine, but it does conflict with a common workflow: being strict with third-party dependencies while remaining more lenient with internally maintained packages.
@wraithgar acknowledged this as a separate concern:
Excluding packages is wholly separate from this new parameter. It was excluded in the interest of solving one problem at a time.
This issue is intended to track that next step and continue the discussion from #8825.
Use case
Organizations that publish internal packages (e.g., @myorg/shared-utils) often need to deploy updates immediately, while still wanting the safety net of min-release-age for external dependencies. Without an exclusion mechanism, adopting min-release-age means either applying it uniformly (blocking internal updates) or not using it at all.
Prior art
- PR feat: add minimum package age policy to prevent supply chain attacks #8825 proposed
minimum-release-age-excludeas an array of package names - pnpm's
minimumReleaseAgewas the original inspiration (Add a way to enforce a minimum package age policy pnpm/pnpm#9921)
Open questions
- Naming:
min-release-age-excludeto align with the merged config, or another convention? - Should it support glob patterns (e.g.,
@myorg/*) or exact package names only? - Any other considerations from the npm team?
Activity
yeikel commentedon Feb 19, 2026
Some thoughts:
min-release-age-excludesounds reasonable to meTo stay consistent with other package managers, we should likely support glob patterns. Whether we include that in the initial release or address it in a follow-up is something we can decide.
The following package managers implemented glob patterns:
pnpm
Yarn
Dependabot (not exactly a package manager but it is worth mentioning)
camelmasa commentedon Feb 20, 2026
Thanks for the thorough research, @yeikel.
I agree that glob pattern support (e.g.,
@myorg/*) makes sense — it's clearly the standard across pnpm, Yarn, and Dependabot.Whether to include glob support in the initial release or as a follow-up is something I'd leave to the maintainers to decide based on their roadmap and priorities.
camelmasa commentedon Feb 21, 2026
@wraithgar Would love to hear your thoughts on this when you get a chance. You mentioned in #8965 that excluding packages is separate — this issue is meant to track that next step. Any guidance on direction would be appreciated.
jnloureiro commentedon Mar 9, 2026
npm already offers syntax for this use case in the form of
@myorg:registry=..., though it only seems to be functional for registry configuration. Maybe it could be used here as well?Additionally, would this option only limit the scoped packages themselves or would it also limit all of their dependencies?
A scoped package with a third-party dependency that's more recent than the configured minimum age would potentially compromise the security this feature intends to offer. If, instead, third-party dependencies of scoped packages must obey the minimum age configuration, conflicts may arise with the dependency versions declared by the package.
SchroederSteffen commentedon Mar 27, 2026
Related:
BruceHubbard commentedon Apr 17, 2026
Without having a mechanism to exclude certain packages
min-release-ageis not nearly as useful as it could be. What happens when a security vulnerability comes in and a particular package needs to be updated? What would the process be? Do we basically have to:min-release-agendays and then reintroducemin-release-ageThat would leave us vulnerable for those
ndays and would require 2 PR's. How are those that are usingmin-release-agehandling it when you need to update a package that is<ndays old? That is definitely a scenario that is going to happen.nikwen commentedon May 1, 2026
I just tested. This part is not necessary.
This works:
min-release-agemin-release-ageBruceHubbard commentedon May 1, 2026
@nikwen Thanks! I'm guessing after your remove
min-release-ageand then update the package it is adding the package to the lock file. Does that mean that npm will install packages less thanndays old as long as it is in the lock file? Or is this because you had the package cached locally? I don't want to do this locally and then have it fail in a pipeline where that package isn't cached.nikwen commentedon May 1, 2026
@BruceHubbard Yes, it seems to be because it modifies the lockfile. Running
npm installon a computer that didn't have the package cached worked fine.Bafff commentedon May 1, 2026
As far as I understand - if you are not utilizing lockfiles (do not use npm ci and just run npm install for example) you will have the same problem in CI.
Is that correct?
Bafff commentedon May 1, 2026
I think
npm install sax --min-release-age=0is a bit cleaner wayBruceHubbard commentedon May 1, 2026
@nikwen OK that's great! I guess I incorrectly thought that even if the package was in the lock file that if it was less than
ndays old it still wouldn't install the package but this works for me.mikkelblanne commentedon May 4, 2026
No, in the simple case (no changes to package.json) npm install also uses the lock file.
The best current approach appears to be:
min-release-age=Xto .npmrc--min-release-age=0to i.e.npm installornpm update.Consequences:
npm installandnpm cion other clients.npm install @acme/pkg --min-release-age=0bypass command, you will also get the very latest versions of all dependencies pulled in by that package. This is whatmin-release-age-excludeshould help with.dwolrdcojp commentedon May 13, 2026
sigh
Can this be moved up in priority now?
rouse-bruno-favero commentedon May 13, 2026
With the current increase in supply chain attacks having the min age flag is very important but at the same time this blocks installing private packages, we need this exclusion flag supported asap please.
fix(cooldown): correct per-PM native config keys + real --check enfor…
fix(cooldown): hook stays engaged on npm for the allowlist; never --b…
docs(cooldown): correct per-PM keys/units, document npm-no-exclude; b…
feat(npm,pnpm): add supply-chain release-age embargo
feat(npm,pnpm): add release-age embargo to user npmrc
runephilosof-abtion commentedon May 18, 2026
As far as I can tell, it is blocked by npm/rfcs#868, so head over there and contribute, if you want it resolved faster.
The comment that lead me there #9175 (comment), and then npm/rfcs#861 (comment)
rjgotten commentedon May 19, 2026
I.e. you could just bring that idea full circle as:
This seems insanely more simple than any kind of custom exclusion list syntax.
wanjakrah commentedon May 19, 2026
This would make sense, since you should also have to add configuration to limit your @myorg to your private repo as well. Otherwise, people could clone your internal project name and upload a compromised version with a newer version to a public repo, and together with your exclusion, you would still pull the compromised version from the public repo.
jamie-tm commentedon May 19, 2026
You should always own your private scope in the public registry, even if you don't actually publish any packages into it. You never want to let someone else upload a version with the same name.
Ashwin2397 commentedon Jun 6, 2026
Hey guys, any update on when this will be worked on? Is it possible to move this up in priority?
feat(cooldown): emit documenting header naming the own-scope override…
Support npm in gestate trust via min-release-age-exclude (npm >= 11.1…
grafanauser commentedon Aug 11, 2026
negative side effects:
I want to update myCompany@myPackage from 1.0.0 to 1.0.1 because i changed some code but did not chance any dependencies. I dont want that this update also updates a transient dependency like express from 4.22.1 to 4.22.1 because it is set to
express: ~4.22.0by a package used by myCompany@myPackage.example dependencies tree: