Supply Chain

NuGet's September 2025 Trusted Publishing Launch and the 2026 Signing Roadmap

NuGet became the fifth major registry to ship Trusted Publishing in September 2025, with .NET package signing and ID prefix reservation forming a complete trust-signal stack for the ecosystem.

Shadab Khan
Security Engineer
6 min read

The September 2025 rollout of Trusted Publishing on NuGet was widely-reported (Andrew Lock's blog post is one of the cleaner write-ups) but somewhat overshadowed by the simultaneous Shai-Hulud crisis on npm. From a defender perspective the NuGet rollout deserves more attention than it got: it closes the last major registry where production publishing still defaulted to long-lived API keys, and it lands on top of an existing ID prefix reservation system and a package-signing infrastructure that .NET has run since 2018. This post walks through the combined trust-signal stack on NuGet as of 2026, what changed in the September 2025 release, and how a consuming organization should be reading the signals.

What did NuGet change in September 2025?

NuGet shipped OIDC-based Trusted Publishing for GitHub Actions, with the same pattern PyPI and crates.io use: a publisher configures a trusted-publisher record in NuGet.org tying a specific GitHub repository and workflow to a package, the CI workflow requests an OIDC token from GitHub's well-known endpoint, exchanges it for a short-lived NuGet API key, and publishes. The trusted-publisher claim is recorded in the package's NuGet.org metadata and visible on the package's public detail page. Andrew Lock's write-up walks through the exact GitHub Actions YAML needed and notes that the new flow eliminates the need to store any long-lived NuGet API key in repository secrets. The launch coincided with the broader Microsoft .NET supply-chain push that has included Scorecard integration, the .NET package signing requirements, and the long-running ID prefix reservation program.

How does this fit with NuGet's existing trust-signal stack?

NuGet has carried a more layered trust-signal model than most package ecosystems for several years. Package signing has been required for NuGet.org submissions since 2018, with two distinct certificate types: author-signing certificates (the publisher's identity) and repository-signing certificates (NuGet.org's own signature, applied at ingestion to every published package). ID prefix reservation, documented at learn.microsoft.com/en-us/nuget/nuget-org/id-prefix-reservation, lets package owners reserve namespace prefixes like Microsoft. or Azure. so no other publisher can register a package starting with that prefix. Together with Trusted Publishing, the stack now offers four distinct signals: a signed package, a reserved namespace, an OIDC-attested publisher, and (where the publisher cross-files) a public provenance attestation through the GitHub Actions OIDC chain.

What signals can a consumer read on a NuGet package?

Four signals are visible on every package detail page and through the NuGet API. The first is the author-signing certificate, with the subject and issuer surfaced so consumers can verify that the signer matches the expected publisher identity. The second is the prefix-reservation badge, indicated by a check mark next to the package owner on packages whose ID falls under a reserved prefix; this is the .NET ecosystem's typosquatting defense. The third is the trusted-publisher claim, new in September 2025, which records the GitHub repository and workflow that produced the package. The fourth is the package's vulnerability metadata pulled from the GitHub Advisory Database, which dotnet list package --vulnerable consumes for client-side reporting. None of these signals individually defeats a determined attacker, but the combination makes namespace squatting, maintainer takeover, and credential theft each measurably harder.

How do you verify a NuGet package before consuming it?

The .NET CLI ships verification commands that cover both signature and vulnerability checks. For provenance verification of Trusted Publishing claims, the GitHub-issued OIDC token chains can be checked using cosign against the Sigstore public-good instance.

# Verify package signatures and certificate chain
dotnet nuget verify path/to/Package.1.2.3.nupkg \
  --certificate-fingerprint <expected-fingerprint>

# Check installed packages against the vulnerability database
dotnet list package --vulnerable --include-transitive

# Verify prefix reservation through the NuGet API
curl -s "https://api.nuget.org/v3/registration5-semver1/your-pkg/index.json" | \
  jq '.items[].items[].catalogEntry | {id, version, owners, verified}'

# For Trusted Publishing claims, fetch the package metadata and inspect
# the publishing-provenance fields
nuget locals all -list

For organizations consuming NuGet through an internal proxy like Artifactory, Nexus, or GitHub Packages, the same checks apply against the proxied artifact and the signature verification is preserved through the mirror.

What policy gate catches the .NET-specific attack class going forward?

Three gates align with the trust-signal stack. Gate one is "require a valid author signature matching an org allow-list for any production NuGet package," which neutralizes the unsigned-package class and forces an explicit decision on which publisher identities are trusted. Gate two is "prefer prefix-reserved packages and alert on any new dependency whose ID looks similar to a reserved namespace but is not itself reserved," a typosquatting check that is unusually well-supported by .NET because of the reservation infrastructure. Gate three is "require Trusted Publishing claims for tier-one dependencies added or upgraded after a defined cutoff," matching the policy stance from the broader cross-ecosystem Trusted Publishing rollout. The combination is achievable today; the work is mostly in policy authoring rather than tooling.

What did the .NET ecosystem learn from the broader 2025 supply-chain events?

The .NET community's response to the 2025 npm and PyPI waves was unusually measured: because NuGet already required signing, the worm-style propagation patterns that hit npm were structurally harder to replicate against NuGet. The September 2025 reputation-hijacking research, where attackers attempted to mimic legitimate publisher names without holding a reserved prefix, did find some traction, but the ID prefix reservation system meant the most damaging namespaces remained protected. The broader takeaway from the .NET team's perspective, documented across the NuGet blog and Microsoft Learn documentation, is that defense-in-depth at the registry level pays off precisely during ecosystem-wide stress events: NuGet did not need an emergency response posture in September 2025 because the structural controls already in place limited the attack surface.

What still has to mature?

Two gaps remain. The first is non-GitHub CI integration. NuGet's Trusted Publishing currently supports GitHub Actions; Azure DevOps integration is on the roadmap given the Microsoft heritage of both products, and other CI systems will follow. The second is downstream consumer adoption of the signature-verification step. While NuGet signs every package, many .NET teams do not explicitly verify signatures during install, partly because the default toolchain handles it transparently and partly because the broken-signature failure mode has historically been rare. The 2026 best-practice recommendation is to explicitly enable strict signature verification in CI so a broken or unexpected signature fails the build rather than silently degrading to "unsigned but installed."

How Safeguard Helps

Safeguard's NuGet support handles the full .NET trust-signal stack: author-signature verification, prefix-reservation lookup, Trusted Publishing claim consumption, and vulnerability cross-reference against the GitHub Advisory Database. Per-tier policies can require valid author signatures from an org allow-list, enforce prefix-reservation for tier-one dependencies, and alert on any new package whose name resembles but does not match a reserved prefix. The provenance verification engine consumes NuGet Trusted Publishing claims alongside the equivalent claims from npm, PyPI, RubyGems, and crates.io, giving defenders a single policy grammar across every ecosystem they consume. Malicious-package feed integration covers NuGet.org takedowns and the GitHub Advisory Database in a single stream, and the postinstall-script audit story extends to NuGet's tools/ and install.ps1 lifecycle hooks the same way it covers npm postinstall. The result is that the same defender posture you apply to npm and PyPI translates directly to your .NET dependency graph without per-ecosystem tooling.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.