user

How to Filter Unwanted Packages from NuGet.org

Introduction

Eric Seng

Eric Seng


LATEST POSTS

What are NuGet Package Vulnerabilities and How to Manage Them 09th October, 2023

How to Debug NuGet Packages with Symbols and Source Link Painlessly 02nd October, 2023

NuGet

How to Filter Unwanted Packages from NuGet.org

Posted on .

NuGet packages need to be checked and verified before use – everyone knows that. But how can you balance security checks with your packed schedule?

It’s simple: create a filter that blocks unwanted packages from NuGet.org!

Filters can be created in ProGet and used in tandem with your package approval process to prevent packages with vulnerability, quality, or licensing issues from making it through to production. Of course, you should be checking and verifying packages meet a certain standard before using them. But checking the same packages repeatedly after every small patch is a huge pain. Using Connector Filters makes it much more convenient for senior developers to verify packages and for junior developers to get the packages they need.

In this article, I’ll walk you through how to configure Connector Filters in ProGet to implicitly allow or block NuGet packages.

What is a Connector Filter?

Connectors allow ProGet feeds to include packages from an external source,  whether it’s another ProGet feed, a third-party package source like Azure DevOps Packages, or NuGet.org.

Connector Filters are conceptually simple. On a NuGet.org connector, just add a filter, enter a name (with, or without a “*” wildcard), and then indicate whether packages with that name (package ID in NuGet) are “blocked” or not.

Connector Filters allow you to implicitly allow/block:

  • All versions of a specific package
  • All versions of all packages with a certain prefix (i.e. organization)

Using filters, you can allow packages that come from a trusted source, meaning that you don’t have to verify/scan packages that you know will pass.

For example, AWSSDK.Core is updated up to twice WEEKLY. That’s a lot of time spent scanning the same package over and over if you’re doing it manually.

Connector Filters also allow you to block packages that you know are untrustworthy, preventing potential dependency confusion attacks.

If your team has an already established process to verify and approve packages, Connector Filters make an excellent addition to this process. Your package approval workflow explicitly allows/blocks packages. Meaning someone looks at a single version of a single package and makes a judgment on whether or not it passes. But that judgment only applies to that ONE version of that ONE package.

Connector Filters work to implicitly allow/block packages. This means that all versions of all packages with a certain name or prefix are automatically allowed or blocked.

Using Connector Filters, you could add a filter to implicitly allow all System.* packages. This filter would then allow all packages with the prefix (i.e. organization) “System” which are a part of .NET’s core libraries. You could also add a filter to block all versions of a single package like StructureMap. This would implicitly block all versions of StructureMap, an effectively dead package.

No Package Approval Workflow?

An established package approval workflow isn’t a prerequisite for using Connector Filters, but I’d suggest setting one up. A package approval process is just like a code review but for packages. It can be as casual as sending an email to an approver OR it could have a formal gated process where multiple people sit in a room and discuss it.

Creating a standard package approval workflow simplifies the approval process for developers & approvers, ensures all the packages your team is using pass a quality check and makes it extremely easy for developers to access all the packages they need.

But for teams that are comfortable with fewer restrictions and want to work without an approval workflow, you basically have two choices:

  • Create a highly-restrictive feed that only has packages from a handful of prefixes (Microsoft.*, System.*)
  • Create a mostly-unrestricted feed that only blocks from a handful of prefixes like MyCompany.*

While ProGet has no limit on the number of filters, you don’t want to use it in place of a package approval workflow. Hundreds of filters will be hard to maintain, and because they allow all versions (past and future), the decision to filter them later may change.

Setting Up a Connector Filter in ProGet

Navigate to your NuGet feed in ProGet and click on Manage feed.

Any current rules this feed may have will be shown at the bottom of this page. To create a new allow/block rule click “Add Filter.”

By default, ALL packages are allowed. So, in order to only allow packages, you want you must first create a rule that blocks all packages.

You can also configure what it means when a package is “blocked” by clicking “configure filtering.” In all cases, a blocked package can’t be downloaded, but you can partially hide it (i.e. you can navigate to the package in the UI directly by URL), or totally hide it (you can’t even browse to it).

Filters enable implicit approval so you can implicitly allow or prohibit:

  • All versions of a specific package
  • All versions of all packages with a certain prefix (i.e. organization)

Using Connector Filters in conjunction with an approval workflow allows you to filter the connector on your “unapproved-nuget” feed with packages that will never be approved (e.g. StructureMap, MyCompany.*)

You are also able to add a filtered connector to your “approved-nuget” feed with packages that will always be approved (e.g. System.*, AWSSDK.Core.)

Best Practices 

Block Your Company’s Prefix (e.g. MyCompany.*):

All the packages in your organization should start with the name of your company (e.g. MyCompany.*), and that means there should be no legitimate package that starts with “MyCompany.” on NuGet.org.

At best, it could be a mistake. At worst, it might be a dependency confusion attack or another way to get seemingly legit packages snuck into your supply chain.

Don’t Add Rules for Infrequently Updated Packages (e.g. Newtonsoft.Json):

Newtonsoft.Json is another package engineers need access to. However, since it’s only updated twice a year, it’s much more reasonable to have it manually reviewed.

Allow Integral Packages That are Frequently Updated (e.g. AWSSDK.Core)

AWSSDK.Core is an integral package engineer need access to and is updated up to twice a week. That would be a lot of manual approval. Using a Connector Filter is the perfect way to balance package verification and an approver’s schedule.

Allow Packages with Trusted Prefixes (e.g. System.*):

With packages hosted at NuGet.org. Organizations can apply for an ID Prefix Reservation. Once approved, only that organization can publish packages with that prefix. “System.” Is reserved by Microsoft, and it refers to a package integral to .NET and therefore can be trusted.

Side Note About Prefixes: Organizations can apply for an ID Prefix Reservation and once approved, only that organization can publish packages with that prefix. However, this rule is quite recent and there are handfuls of package names that were “grandfathered” in. These outliers are able to retain their previous names due to the fact that the package had that name before the rule and some organizations might run into SERIOUS issues in NuGet just switches the names all of a sudden.

For example System.Linq.Dynamic.Core is by zzzprojects, not Microsoft even though Microsoft now owns the “System” prefix. This could be a good case for implicitly blocking that name.

Next Steps

Balancing NuGet best practices and a busy schedule is a tough act. Connector Filters help by removing unnecessary scanning and providing packages to developers when they need them.

But this is only the tip of the iceberg when it comes to taking your NuGet packages to the enterprise. Sign up for our mailing list to receive our upcoming guide that will guide you on everything from NuGet Connector Filters to CI/CD for NuGet packages.

Eric Seng

Eric Seng

Navigation