Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block Versions Based on Some Filter #818

Closed
mlucool opened this issue Jul 16, 2018 · 11 comments
Closed

Block Versions Based on Some Filter #818

mlucool opened this issue Jul 16, 2018 · 11 comments

Comments

@mlucool
Copy link
Contributor

mlucool commented Jul 16, 2018

Is your feature request related to a problem? Please describe.
Recent issues with community published libraries either malicious or not are generally caught by the community quickly. I'd like to come up with a defense against these types of issues.

Describe the solution you'd like
The ability to create a plugin that allows for fine grained, rule based control of if a package appears to exist to npm clients.

For example, I could create a rule that says a package must have been published at least X days ago before the registry proxy claims it exists to clients. This would take us off bleeding edge, but lower the risk of major issues. I would also be able to do things like feed it a blacklist of libraries that no one should be able to download (e.g. in the days before npm grabbed this, we would block it). A good design would allow for easy admin and escape hatches to let new versions flow through. It may also consider allowing clients the ability to override this depending on the design and trust model we want to build.

There is clear risk here and moving away from a simple proxy and increasing the complexity and management of a proxy, but given the seriousness of recent issues, I believe would add a good line of defense.

What do you think?

@juanpicado
Copy link
Member

It relates with #810

@juanpicado juanpicado added this to the Future milestone Jul 17, 2018
@juanpicado
Copy link
Member

I like the idea, but we would need to elaborate a bit more what are the boundaries and whether is possible with the current design + being optional

@mlucool
Copy link
Contributor Author

mlucool commented Jul 17, 2018

Not having looked deeply into this yet, I imagined this would work by looking at the json object that has all metadata (e.g. this). When verdaccio goes to return this (or derived info from this) it would first parse this object and pass it to a plugin (where the default passes it through unchanged). This plugin could then do whatever it wanted to modify this source of truth. The rest of this proxy would have to obey that vision of the world.

One example plugin would be one that takes in the rules described above and removes blacklisted and/or temporarily barred versions. If today where 2018-07-12 and my plugin was set to only allow packages that are at least one day old through, it would look first find the following times in the above example:

   "time":{  
      "modified":"2018-07-12T17:51:58.205Z",
      "created":"2017-03-17T22:10:11.109Z",
      "3.7.0":"2017-03-17T22:10:11.109Z",
      "3.7.1":"2017-04-12T21:13:31.158Z",
      "4.0.0-alpha.0":"2018-04-28T01:47:18.036Z",
      "4.0.0-rc.0":"2018-06-09T15:59:17.350Z",
      "4.0.0":"2018-06-21T20:41:41.408Z",
      "3.7.2":"2018-07-12T10:40:00.478Z",
      "3.7.3":"2018-07-12T17:41:22.504Z"
   },

From there, it would remove 3.7.2 and 3.7.1 as they are both less than 24 hours old and any other blacklisted version. My npm client would be none the wiser that 3.7.2/3.7.1 exist and things would all be ok.

This could break end users in an odd way if your blacklist makes modules that are required implied dependencies appear to not exist. It would be better if we had some clear feedback mechanism for this case, but this is still much safer.

@mlucool
Copy link
Contributor Author

mlucool commented Jul 31, 2018

Hi @juanpicado, any more thoughts on this?

@juanpicado
Copy link
Member

@mlucool I haven't had time yet, sorry.

@mlucool
Copy link
Contributor Author

mlucool commented Aug 3, 2018

I spent some time on this. I would I was able to remove packages by adding in a function in storage.getPackage that pruned the result by deleting both the time and versions key for that specific version.
e.g.

delete result.versions[badVersion];
delete result.time[badVersion];

The only major issue with this approach is if you delete something that is a also a dist-tag you have to do some sort of repair. I also don't know if this is all that is necessary, but testing showed this is sufficient for the npm i case.

Therefore, I propose we add in a plugin with an API of one function, filter. This will be called on every call to getPackage. A noop implementation of this is the identity function.

What do you think? Worth pursuing?

@juanpicado juanpicado added this to Brainstorming in Verdaccio 4 Sep 12, 2018
@juanpicado juanpicado removed this from (Under consideration) in Verdaccio 4 Nov 30, 2018
mlucool added a commit to mlucool/verdaccio that referenced this issue Dec 13, 2018
Add a plugin that can filter all packages before being returned. This
enables blocking at the verdaccio level.

Fixes: verdaccio#818
@mlucool
Copy link
Contributor Author

mlucool commented Dec 13, 2018

@juanpicado I created an WIP in #1161 for what I think could create a plugin based approach to solve this. What do you think of this concept? If you like it, what do you think are the next steps to get this ready for merging? I know I need to refactor this so external plugins can be created and add unit testing.

mlucool added a commit to mlucool/verdaccio that referenced this issue Dec 18, 2018
Add a plugin that can filter all packages before being returned. This
enables blocking at the verdaccio level.

Fixes: verdaccio#818
@juanpicado juanpicado modified the milestones: Future, 4.2.0 Feb 13, 2019
mlucool pushed a commit to mlucool/verdaccio that referenced this issue Apr 16, 2019
Add a plugin that can filter all packages before being returned. This
enables blocking at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue Apr 16, 2019
Add a plugin that can filter all packages before being returned. This
enables blocking at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue Apr 16, 2019
Add a plugin that can filter all packages before being returned. This
enables blocking at the verdaccio level.

Fixes: verdaccio#818
@juanpicado juanpicado modified the milestones: 4.2.0, 4.1.0 Apr 17, 2019
@juanpicado juanpicado added this to To do in Development 4.x via automation Apr 17, 2019
@juanpicado juanpicado moved this from To do to In progress in Development 4.x Apr 17, 2019
mlucool pushed a commit to mlucool/verdaccio that referenced this issue Apr 17, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of bad packages at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue Apr 17, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of bad packages at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue Apr 18, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of bad packages at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue Apr 18, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of bad packages at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue Apr 19, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of bad packages at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue May 6, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of bad packages at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue May 15, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of bad packages at the verdaccio level.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue May 16, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of packages from verdaccio.

IPluginStorageFilter are loaded like other plugins from the config.
Verdaccio will look for plugins in config.filters and pass this to
storage.init. This is the same design as other plugins and will be
dynamically found with the same rules. These plugins must impliment
a filter_metadata method, which is called serially (in the order
loaded from the config) for every metadata request. It gets a current
copy of a package metadata and may choose to modify it as required.
For example, this may be used to block a bad version of a package or
add a time delay from when new packages can be used from your
registry. Errors in a filter will cause a 404, similar to upLinkErrors
as it is not safe to recover gracefully from them. Note: When version
is removed, be careful about updating tags.

Fixes: verdaccio#818
mlucool pushed a commit to mlucool/verdaccio that referenced this issue May 16, 2019
Add a plugin that can filter all package metadata before being returned.
This enables blocking of packages from verdaccio.

IPluginStorageFilter are loaded like other plugins from the config.
Verdaccio will look for plugins in config.filters and pass this to
storage.init. This is the same design as other plugins and will be
dynamically found with the same rules. These plugins must impliment
a filter_metadata method, which is called serially (in the order
loaded from the config) for every metadata request. It gets a current
copy of a package metadata and may choose to modify it as required.
For example, this may be used to block a bad version of a package or
add a time delay from when new packages can be used from your
registry. Errors in a filter will cause a 404, similar to upLinkErrors
as it is not safe to recover gracefully from them. Note: When version
is removed, be careful about updating tags.

Fixes: verdaccio#818
@mlucool
Copy link
Contributor Author

mlucool commented Jun 20, 2019

Closing as this was completed via #1161

@mlucool mlucool closed this as completed Jun 20, 2019
Development 4.x automation moved this from In progress to Done Jun 20, 2019
@robcresswell
Copy link

@mlucool Was this documented anywhere? I see all the PRs merged, but I can't see anything about filters on the docs site

@juanpicado
Copy link
Member

@robcresswell not extensively https://verdaccio.org/docs/en/dev-plugins#filter-plugin but yes, also the PR contains some information.

@lock
Copy link

lock bot commented Nov 17, 2019

🤖This thread has been automatically locked 🔒 since there has not been any recent activity after it was closed.
We lock tickets after 90 days with the idea to encourage you to open a ticket with new fresh data and to provide you better feedback 🤝and better visibility 👀.
If you consider, you can attach this ticket 📨 to the new one as a reference for better context.
Thanks for being a part of the Verdaccio community! 💘

@lock lock bot added the outdated label Nov 17, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Nov 17, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

No branches or pull requests

3 participants