Overview
Validation.PackageSigning.ProcessSignature is a .NET Framework 4.7.2 console executable that runs as a long-lived Azure Service Bus subscription listener. Its sole responsibility is to validate the cryptographic signatures embedded in .nupkg files. It is the authoritative service that decides whether a package’s author signature is trustworthy, whether an existing repository signature is acceptable, and whether the package must be stripped and re-signed before being made available to consumers.
The job has two distinct operating modes controlled by a single boolean field in the incoming Service Bus message:
- Processor mode (
RequireRepositorySignature = false): Run before the repository-signing step. Strips unacceptable repository signatures and rejects bad author signatures. The package blob may be modified. - Validator mode (
RequireRepositorySignature = true): Run after the repository-signing step. Repeats all the same checks and additionally requires a valid repository signature to be present. The package blob must not change.
Role in the NuGetGallery Ecosystem
NuGet.Services.Validation.Orchestrator. It reads and writes to three external stores: the Validation SQL DB (validator state, package signatures, certificate chain), the Gallery SQL DB (certificate display metadata, package signing certificate fingerprint), and Azure Blob Storage (raw DER-encoded certificate files and the modified .nupkg when signatures are stripped).
Key Files and Classes
Dependencies
NuGet Packages (via Validation.Common.Job and transitive references)
Internal Project References
Notable Patterns and Implementation Details
Two-pass validation design: The same executable handles both the pre-signing processor pass and the post-signing validator pass. The only difference is the
RequireRepositorySignature flag on the incoming Service Bus message. This avoids duplicating signature validation logic across two separate services.Repository signature stripping: When a package arrives with a repository signature whose V3 service index URL or signing certificate does not match the configured allow-list, the job rewrites the
.nupkg blob using SignedPackageArchiveUtility.RemoveRepositorySignaturesAsync and uploads it with a READ+DELETE SAS token. The orchestrator then uses this new URL for the subsequent repository-signing step.Certificate extraction is one-way immutable for author signatures:
SignaturePartsExtractor enforces that the end-certificate thumbprint and timestamp value for an author PackageSignature record can never change once written (allowSignatureChanges: false). Repository signature records are replaceable (allowSignatureChanges: true) because the repo signing certificate can rotate.MinimalSignatureVerificationProvider is intentionally a no-op: The minimal verification pass uses a provider that always returns Valid. Its purpose is purely to exercise the NuGet client’s signature-format parsing so that any SignatureException is caught and translated into a user-facing ClientSigningVerificationFailure rather than propagating as an unhandled exception.Idempotency via
IValidatorStateService: On receipt of a message, the handler immediately checks the Validation DB. If the record is missing or in NotStarted state the message is retried (returns false). If the record is already in a terminal state the message is consumed without re-running validation (returns true). This makes the handler safe to receive duplicate messages.