Skip to content

feature: Add denied-version support to block downloading/accessing specific package versions#5505

Open
pyhp2017 wants to merge 4 commits intoverdaccio:masterfrom
corticph:work-on-omit-denied-versions
Open

feature: Add denied-version support to block downloading/accessing specific package versions#5505
pyhp2017 wants to merge 4 commits intoverdaccio:masterfrom
corticph:work-on-omit-denied-versions

Conversation

@pyhp2017
Copy link

@pyhp2017 pyhp2017 commented Dec 3, 2025

We needed a way to hard-block specific npm package versions so compromised releases can’t reach developer workstations. This PR adds a configurable deniedVersions list per package, wires a reusable filter through storage/search/tarball flows, and ensures any denied version is hidden from manifests, search results, and downloads-keeping teams safe from known-malicious builds.

@pyhp2017 pyhp2017 marked this pull request as ready for review December 4, 2025 09:18
@pyhp2017 pyhp2017 changed the title Add denied-version support to block downloading/accessing specific package versions feature: Add denied-version support to block downloading/accessing specific package versions Dec 4, 2025
@juanpicado juanpicado self-requested a review December 7, 2025 10:29
Comment on lines +112 to 113
this.deniedVersionFilter = new DeniedVersionFilter(config);
this.filters = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is great, I just need to give some thoughts to this, because we might end up with two filter systems. There is already a plugin that meant to filter out versions.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Junapicado,
sorry for the late reply - could you please explain more about this plugin? i couldn't find it thats why i developed this. i think it's a good idea to have it inside the program itself. since as far as i know there were some requests in the issues which this could help.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would be happy to hear your ideas and implement those as well. feel free about that :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is the plugin that I was talking about
#5509 (comment)

But I agree, I've been thinking lately to integrate it at the core by default due the latest incidents, I need to close other topics around here first to, please remind me if I don't comment after some time.

Copy link
Member

@juanpicado juanpicado left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀

@mbtools
Copy link
Collaborator

mbtools commented Dec 10, 2025

This can already be done with existing filter plugins. You can find them at https://www.verdaccio.org/dev/plugins-search.

https://www.npmjs.com/package/verdaccio-plugin-delay-filter is the most recent and has plenty of options like block, allow, replace, and delay. It also takes semver ranges as config.

@juanpicado
Copy link
Member

This can already be done with existing filter plugins. You can find them at https://www.verdaccio.org/dev/plugins-search.

https://www.npmjs.com/package/verdaccio-plugin-delay-filter is the most recent and has plenty of options like block, allow, replace, and delay. It also takes semver ranges as config.

yeah, I was checking in detail and https://www.npmjs.com/package/verdaccio-plugin-delay-filter does pretty much the same thing and kind might get in conflict as visible here:

Screenshot 2026-01-01 at 20 58 41

Aside of that, to provide feedback regarding the implementation I see a potential misusage on https://github.com/verdaccio/verdaccio/pull/5505/changes#diff-04f5a415e28acd604a98982813713b38bdc78dbea8b2a5328f273a114f283de4, for instance, if someone does

  '*':
    access: $all
    publish: $authenticated
    proxy: npmjs
    deniedVersions:
      - 1.0.0
      - 2.0.0

it would cause troubles, the plugin verdaccio-plugin-secfilter is more deterministic regarding what should filter, goes for scopes or a specific package (see readme of that package).

I think what we should do instead, is asking you and @vsugrob to find the way to merge both approaches and include the a a new updated filter plugin build-in at verdaccio under verdaccio scope hosted on this project. Thoughts ?

@vsugrob
Copy link
Contributor

vsugrob commented Jan 2, 2026

Hi! I'm sure I can find some time for this idea. @pyhp2017, if you have time, please see my plugin description and share thoughts on what is missing for your use cases. At its current state my plugin successfully handles filtering large npm installs without breaking anything in the process. It took some effort to figure out how to handle variety of scenarios and cover them with tests.

@pyhp2017
Copy link
Author

pyhp2017 commented Jan 4, 2026

Hi @vsugrob thank you for your message - one of the problems that i've found with plugin is that you can still get the denied version when you search:

npm search @posthog/cli --registry=http://127.0.0.1:4873

output:

@posthog/cli
The command line interface for PostHog 🦔
Version 0.5.21 published 2025-12-29 by GitHub Actions
Maintainers: watilo twixes fuziontech mariusandra ben-posthog timgl fraserhopper manoelposthog robbie-c frankposthog tom-posthog adamleithp peterkirkhamposthog joshuasnyder huguespouillot
https://npm.im/@posthog/cli

and the config:

filters:
  plugin-delay-filter:
    block:
      - package: '@posthog/cli'
        versions:
          '0.5.21' # block some malicious versions of previously ok package

it doesn't show it on UI and it's not downloadable but it should probably filter out the search as well. in my proposed change filter on search also happens - maybe you can apply the same logic on plugin?

@vsugrob
Copy link
Contributor

vsugrob commented Jan 4, 2026

@pyhp2017 I'll look into it. Filter plugin functionality is young in verdaccio and things like that are likely to happen. It's really good you found it. I think I'll have time for this at the end of the January.

@RealAlphabet
Copy link

Thanks a lot for this work, exposing more context to auth plugins is definitely a step in the right direction, and it already unlocks several useful use cases.

I spent some time testing the current behavior with real npm flows, especially around CI and ephemeral credentials, and I wanted to share a complementary observation.

Even with the additional fields (version, tag) exposed to auth plugins, version-level enforcement remains inherently limited today:

  • pkg.version is undefined when resolving latest or during lockfile-driven installs.
  • Auth hooks are not invoked per version, and metadata endpoints can still list all available versions.

As a result, auth plugins still cannot reliably enforce policies such as:

This credential may only access a specific allowlisted set of versions.

I don’t see this as a limitation of this PR, but rather as a natural boundary of package-level authorization.

Based on this, I opened a follow-up proposal that builds on this work and tries to address the next layer:
version visibility and filtering at metadata resolution time, via an optional allow_access_versions hook:
https://github.com/orgs/verdaccio/discussions/5533

The idea is not to change npm semantics, but to give auth plugins a way to filter the resolved version list before it is exposed to the client, which is required for strict Zero Trust / CI use cases.

This PR feels like an important prerequisite for that direction, so thanks again for pushing this forward — happy to provide concrete examples or test results if helpful.

@mbtools
Copy link
Collaborator

mbtools commented Jan 6, 2026

IMHO solutions that either change Verdaccio storage (package.json) or configuration (verdaccio.yaml) are doomed from the start. The former will cause all sort of sync issues with uplinks. The later will require potentially frequent server restarts.

Therefore, a plugin approach, which can dynamically read and apply rules, is preferred (see my comments in github.com/orgs/verdaccio/discussions/5533).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants