The Authors field
in every NuGet package is free text. Anyone can claim
Authors = "Microsoft"
— and neither Visual Studio nor the .NET CLI will warn you.
nuget-audit uses nuget.org's cryptographically
backed publisher verification, not self-reported metadata. It is also the enforcement
layer for the full zero-trust NuGet workflow — from project setup through CI gate —
and verifies that every control is in place.
dotnet tool install -g nuget-audit
— requires .NET 8 SDK or later
Package Source Mapping, lock files, Dependabot, and vulnerability scanning are all valuable — but each covers a different slice. None of them surfaces the one signal that matters most: whether the publisher is actually who they claim to be.
| What you might already have | Publisher identity | Detection window | Enforcement gate | Setup advisory |
|---|---|---|---|---|
dotnet list package --vulnerable |
No — CVEs only | No | No | No |
| Package Source Mapping | No — feed isolation only | No | No | No |
NuGet lock files + RestoreLockedMode |
No — graph pinning only | No | Partial | No |
| Dependabot | No | Can auto-merge within window | No | No |
| nuget-audit audit --check | Yes | Yes — flags recent versions | Yes — exit code 1 | Yes — warns on missing setup |
nuget-audit audit --check in CI is a single pass/fail gate that covers
all of the above — and warns you when any complementary control is not configured.
By default, only packages that need action are shown. A clean project produces no output and exits with code 0.
Found 2 package(s) needing review.
Type PackageId Version Owners Verified Trust
------ -------------- ------- ------------- -------- -------
Direct Contoso.Http 3.1.0 contoso-oss No Untrusted
Direct SomeLib 2.0.0 known-owner Yes VersionChanged
Recently published (within 14 days):
Contoso.Http 3.1.0 published 3 days ago [Untrusted]
Found 0 package(s) needing review.
No packages match the current filter.
Recently published:
No packages published within
the last 14 days.
Exit code: 0
Run nuget-audit audit --all to see every package with its trust status,
or nuget-audit audit --check for a counts-only CI gate.
Most NuGet supply chain attacks are detected within days of a compromised version being published — by the community, security researchers, or automated scanning. This creates a defensible window: a version in the ecosystem for weeks without incident is meaningfully safer than one published yesterday.
nuget-audit flags any package version published within
recentDaysThreshold days (default: 14) regardless of trust status.
A verified Microsoft.* package published two days ago carries more
risk than one published six months ago — account compromise, insider threat, and
build pipeline compromise do not respect the verified flag.
The recency check also provides substantial coverage for ownership transfer
attacks — where a package is sold or transferred to a malicious actor who
then publishes a compromised version. That version will be flagged as recently
published. The unmitigated residual is a version that ages past the threshold before
the community detects it — an attacker must simultaneously achieve both conditions.
Pair with NuGet package signing (<trustedSigners> in
NuGet.Config) for ownership-transfer detection independent of the
recency window.
Dependabot can auto-merge a dependency PR within hours of a compromised version being published — well inside the detection window. See the Dependabot integration guide for the mitigation pattern.
Each package is evaluated against a layered model. The primary signal is nuget.org
prefix reservation (verified=true) — a cryptographically
backed flag that cannot be self-reported by an attacker, unlike the free-text
Authors field. You configure which verified owners you trust and which
specific package versions you have manually reviewed.
| Condition | Trust Status | Action needed? |
|---|---|---|
| 404 on nuget.org — private or local feed | PrivateFeed | No |
verified=true + owner in trusted owners |
Verified | No |
| Exact ID+version in trusted packages list | TrustedPackage | No |
verified=true + owner not in trusted owners |
VerifiedUnknownOwner | Yes — add owner to trustedOwners if you trust them broadly, or pin the version in trustedPackages for per-version review |
| ID in trusted packages, but version changed | VersionChanged | Yes — urgent, re-review |
| Not verified, not in trusted packages | Untrusted | Yes — review required |
When you see VerifiedUnknownOwner, you have two options:
Add the owner to trustedOwners for publishers you trust
across their entire catalog — well-known organizations like Microsoft, AWS, Google,
whose packages you use broadly and will track as they update. Future packages from
this owner are trusted automatically.
Add the specific version to trustedPackages for
everything else. Even for verified publishers, pinning a version means you explicitly
review each update before it enters your project. This is the more conservative,
zero-trust default — and the version-pinning cost is highest exactly where the
scrutiny should be highest: publishers you haven't fully evaluated.
Uses nuget.org prefix reservation — the only signal an attacker cannot self-report. Not the free-text Authors field.
Flags recently published versions regardless of trust status. Configurable threshold, default 14 days.
Surfaces known vulnerabilities and deprecated packages from nuget.org metadata in the same pass.
Flags packages containing MSBuild targets, Roslyn analyzers, or tool executables — the content that runs at build time.
Resolve the full transitive graph before anything downloads. Review what will land on disk before it does.
Warns when lock files, RestoreLockedMode, the VS pre-build
sentinel, or Package Source Mapping are not configured — and --check
exits 1 on any of these conditions.
--check returns exit code 1 on any package issue or setup
advisory. Clean pass/fail signal for any pipeline or VS pre-build target.
MSBuild target runs --check automatically before each build
when the lock file changes.
dotnet tool install -g nuget-audit
# Create TrustConfig.json and Directory.Build.targets with defaults
nuget-audit init --path .
# Run the audit
nuget-audit audit --path MySolution.slnx
# See the full workflow walkthrough
nuget-audit guide
# Gate 1: restore fails if lock file is out of date
dotnet restore
# Gate 2: audit fails if any packages need review
nuget-audit audit --check --path .
The full team workflow — new projects, package updates, cloning, CI/CD, Dependabot, VS pre-build enforcement, and where the policy can break down — is documented in the zero-trust workflow guide. For individual developers on teams that haven't adopted the policy, see the solo dev workflow.
Requires .NET 8 SDK or later. Runs on Windows, macOS, and Linux.
Install from NuGet.org Read the user guide