About • Download • How To Configure • How To Use • Roadmap • Building • Contributing • Versioning • Credits •
PackageGuard is a fully open-source tool to scan the NuGet dependencies of your .NET solutions against a deny- or allowlist to control the open-source licenses that you want to allow or certain versions of certain packages you want to enforce or avoid.
I've noticed that the commercial solutions for this are usually very expensive and have functionality that smaller companies may not need. Hopefully this little tools fills the gap between tools like GitHub's Dependabot and expensive commercial products like Blackduck, SNYK and others.
My name is Dennis Doomen and I'm a Microsoft MVP and Principal Consultant at Aviva Solutions with 28 years of experience under my belt. As a software architect and/or lead developer, I specialize in designing full-stack enterprise solutions based on .NET as well as providing coaching on all aspects of designing, building, deploying and maintaining software systems. I'm the author of several open-source projects such as Fluent Assertions, Reflectify, Liquid Projections, and I've been maintaining coding guidelines for C# since 2001.
Contact me through Email, Bluesky, Twitter/X or Mastadon
The tool is available as a NuGet Tool package and can be installed like this:
dotnet tool install PackageGuard --global
Then use packageguard --help
to see a list of options.
USAGE:
PackageGuard.dll [path] [OPTIONS]
ARGUMENTS:
[path] The path to a directory containing a .sln file, a specific .sln file, or a specific .csproj file. Defaults to the current working directory
OPTIONS:
-h, --help Prints help information
--configPath The path to the configuration file. Defaults to the config.json in the current working directory
--restore-interactive Allow enabling or disabling an interactive mode of "dotnet restore". Defaults to true
--force-restore Force restoring the NuGet dependencies, even if the lockfile is up-to-date
--skip-restore Prevent the restore operation from running, even if the lock file is missing or out-of-date
First, you need to create a JSON configuration file listing the packages and/or licenses you want to allow/deny list. By default, this file is called config.json
and loaded from the working directory, but you can override that using the --configpath
CLI parameter. The config file needs to have the following format:
{
"settings": {
"allow": {
"licenses": [
"Apache-2.0", // Uses SPDX naming
"MIT",
],
"packages": [
"MyPackage/[7.0.0,8.0.0)"
]
},
"deny": {
"licenses": [],
"packages": [
"ProhibitedPackage"
]
},
"ignoredFeeds": [
"https://pkgs.dev.azure.com/somecompany/project/_packaging/myfeed/nuget/v3/index.json"
]
}
}
In this example, only NuGet packages with the MIT or Apache 2.0 licenses are allowed, the use of the package ProhibitedPackage
is prohibited, and MyPackage
should stick to version 7 only. Both the allow
and deny
sections support the licenses
and packages
properties. But licenses and packages listed under allow
have precedence over those under the deny
section.
License names are case-insensitive and follow the SPDX identifier naming conventions. Package names can include just the NuGet ID but may also include a NuGet-compatible version (range) separated by /
. Here's a summary of the possible notations:
Notation | Valid versions |
---|---|
"Package/1.0" | 1.0 |
"Package/[1.0,)" | v ≥ 1.0 |
"Package/(1.0,)" | v > 1.0 |
"Package/[1.0]" | v == 1.0 |
"Package/(,1.0]" | v ≤ 1.0 |
"Package/(,1.0)" | v < 1.0 |
"Package/[1.0,2.0]" | 1.0 ≤ v ≤ 2.0 |
"Package/(1.0,2.0)" | 1.0 < v < 2.0 |
"Package/[1.0,2.0)" | 1.0 ≤ v < 2.0 |
You can also tell PackageGuard to allow all packages from a particular feed, even if a package on that feed doesn't meet the licenses or packages listed under allow
. Just add the element feeds
under the allow
element and specify a wildcard pattern that matches the name or URL of the feed.
{
"settings": {
"allow": {
"feeds": ["*dev.azure.com*"]
}
}
}
And in case you want to prevent PackageGuard from trying to access a particular feed altogether, add them to the ignoredFeeds
element. Notice that PackageGuard may still trigger a dotnet restore
call if the package lock file (project.assets.json
) doesn't exist yet, unless you use the SkipRestore
option, that will use all available NuGet feeds.
With this configuration in place, simply invoke PackageGuard like this
packageguard --configpath <path-to-config-file> <path-to-solution-file-or-project>
If you pass a directory, PackageGuard will try to find the .sln
files there. But you can also specify a specific .csproj
to scan.
If everything was configured correctly, you'll get something like:
The exit code indicates either 0 for success or 1 for failure.
This is a rough list of items from my personal backlog that I'll be working on the coming weeks.
Complete the MVP
- Allow specifying the location of
dotnet.exe
- Allow ignoring certain .csproj files or folders using Globs or wildcards (e.g. build.csproj)
- Allow marking all violations as a warning
- Allow marking individual violations as a warning
- Make sure passing settings through environment variables work
- Add caching of licenses
- Allow specifying a GitHub token to prevent rate limiting
- Expose the internal engine through the
PackageGuard.Core
NuGet package - Add direct support for Nuke
- Allow loading settings from the directory of the scanned project and move up if not found
- Display the reason why a package was marked as a violation
Major features
- Add support for the new .slnx file
- Add NPM support
To build this repository locally, you need the following:
- The .NET SDK for .NET 8.0.
- Visual Studio, JetBrains Rider or Visual Studio Code with the C# DevKit
You can also build, run the unit tests and package the code using the following command-line:
build.ps1
Or, if you have, the Nuke tool installed:
nuke
Also try using --help
to see all the available options or --plan
to see what the scripts does.
Your contributions are always welcome! Please have a look at the contribution guidelines first.
Previous contributors include:
(Made with contrib.rocks)
This library uses Semantic Versioning to give meaning to the version numbers. For the versions available, see the tags on this repository.
This library wouldn't have been possible without the following tools, packages and companies:
- Spectre.Console - a .NET library that makes it easier to create beautiful console applications.
- Nuke - Smart automation for DevOps teams and CI/CD pipelines by Matthias Koch
- CliWrap - Library for running command-line processes by Oleksii Holub
- Coverlet - Cross platform code coverage for .NET by Toni Solarin-Sodara
- GitVersion - From git log to SemVer in no time
- ReportGenerator - Converts coverage reports by Daniel Palme
- StyleCopyAnalyzer - StyleCop rules for .NET
- Roslynator - A set of code analysis tools for C# by Josef Pihrt
- CSharpCodingGuidelines - Roslyn analyzers by Bart Koelman to go with the C# Coding Guidelines
- Meziantou - Another set of awesome Roslyn analyzers by Gérald Barré
- Verify - Snapshot testing by Simon Cropp
- My Blog
- Reflectify - Reflection extensions without causing dependency pains
- Pathy - Fluently building and using file and directory paths without binary dependencies
- .NET Library Starter Kit - A battle-tested starter kit for building open-source and internal NuGet libraries using "dotnet new", born from half a billion downloads
- FluentAssertions - Extension methods to fluently assert the outcome of .NET tests
- C# Coding Guidelines - Forkable coding guidelines for all C# versions
This project is licensed under the MIT License - see the LICENSE file for details.