Overview
VerifyGitHubVulnerabilities is a recurring, read-only monitoring job that ensures the NuGet Gallery’s vulnerability data stays in sync with GitHub’s Security Advisory Database. It fetches every advisory tagged for the NUGET ecosystem via GraphQL, then walks through the same ingestion pipeline used by GitHubVulnerabilities2Db — but instead of writing to the database it compares what should be there against what is there and logs errors for every mismatch.
This job is intentionally side-effect-free. It opens the Gallery database in read-only mode and never writes to SQL, Azure Blob Storage, or any other persistent store. Its only outputs are structured log entries and Application Insights metrics.
- Database verification — checks that every advisory exists in the
PackageVulnerabilitiestable with the correct severity, advisory URL, and per-versionVulnerablePackageRangeslinkage. - Registration metadata verification — fetches NuGet V3 registration blobs for each affected package and confirms that every version in a vulnerable range carries the correct
vulnerabilitiesarray, and that no out-of-range version is incorrectly tagged.
Role in the NuGet Gallery Ecosystem
GitHubVulnerabilities2Db
Sibling job that actually ingests GitHub advisories into the Gallery SQL database. VerifyGitHubVulnerabilities reuses its GraphQL query layer and ingestion pipeline but substitutes a verifying visitor for the writer.
NuGet Gallery (Web)
Consumes the vulnerability records that this job monitors. Discrepancies reported here indicate that package detail pages or V3 feeds may be serving incorrect security data.
GitHub Security Advisory API
Authoritative source of truth. Queried in full on every run (since epoch) using the same GraphQL query as the ingest job.
NuGet V3 Registration Blobs
The second verification target. The job uses
NuGet.Protocol to download package metadata and inspect the embedded vulnerability arrays directly from CDN-served blobs.Key Files and Classes
| File | Class / Type | Purpose |
|---|---|---|
Program.cs | Program | Console entry point; bootstraps JobRunner from NuGet.Jobs. |
Job.cs | Job : JsonConfigurationJob | Orchestrates the full run: queries GitHub, drives ingestion/verification, emits Application Insights metrics. |
Configuration/VerifyGitHubVulnerabilitiesConfiguration.cs | VerifyGitHubVulnerabilitiesConfiguration | Extends GraphQLQueryConfiguration with NuGetV3Index, VerifyDatabase, and VerifyRegistrationMetadata flags. |
Verify/IPackageVulnerabilitiesVerifier.cs | IPackageVulnerabilitiesVerifier | Extends IPackageVulnerabilitiesManagementService with a HasErrors flag so the job can emit a binary pass/fail metric. |
Verify/PackageVulnerabilitiesVerifier.cs | PackageVulnerabilitiesVerifier | Core verification engine. Implements both DB and registration-metadata checks; registered as SingleInstance in Autofac to accumulate the HasErrors flag across all advisories. |
Scripts/Functions.ps1 | — | PowerShell helpers (Install-NuGetService / Uninstall-NuGetService) used by deploy scripts to manage the Windows service via NSSM. |
Scripts/PreDeploy.ps1 / PostDeploy.ps1 | — | NSSM-based Windows service lifecycle hooks for blue/green deployment. |
Dependencies
Internal Project References
| Project | Role |
|---|---|
GitHubVulnerabilities2Db | Provides the shared GitHub GraphQL query layer (IAdvisoryQueryService, IAdvisoryIngestor, AdvisoryQueryBuilder, GalleryDbVulnerabilityWriter, GitHubVersionRangeParser) and Gallery DB access stubs. |
NuGet.Jobs.Common | Base class JsonConfigurationJob, JobRunner, Key Vault integration, and GalleryDbConfiguration SQL connection helpers. |
NuGet / Framework Dependencies (resolved transitively)
| Package / Namespace | Purpose |
|---|---|
Autofac | IoC container; all services registered in ConfigureAutofacServices. |
Microsoft.Extensions.Configuration | Reads appsettings.json and Key Vault secrets. |
Microsoft.Extensions.Logging | Structured logging throughout; errors are the primary signal. |
NuGet.Protocol / NuGet.Protocol.Core.Types | Downloads V3 registration metadata (PackageMetadataResource) to verify vulnerability arrays in blobs. |
NuGet.Versioning | Parses VersionRange and NuGetVersion strings to determine which package versions fall within a vulnerable range. |
NuGet.Services.Logging | ITelemetryClient used to emit DataIsConsistent / DataIsInconsistent metrics to Application Insights. |
System.Data.Entity (EF6) | Include-based eager loading of Vulnerabilities and AffectedRanges from the Gallery DB. |
Target framework: net472 | Full .NET Framework 4.7.2, required for compatibility with the shared Gallery EF6 context. |
Notable Patterns and Implementation Details
Dual-registration pattern for the verifier.
PackageVulnerabilitiesVerifier is registered in Autofac as both IPackageVulnerabilitiesManagementService (the interface the ingestion pipeline calls) and IPackageVulnerabilitiesVerifier (the interface the job checks for HasErrors). The SingleInstance() lifetime ensures the same object accumulates errors across the entire advisory set before Job.Run inspects it.Full advisory scan on every run. Unlike incremental ingestion jobs,
GetAdvisoriesSinceAsync is called with DateTimeOffset.MinValue, meaning the entire GitHub NuGet advisory corpus is fetched and verified on every execution. This is intentional — the goal is a complete consistency check, not delta processing.Thread-safe metadata caching via
SemaphoreSlim. PackageVulnerabilitiesVerifier fans out verification tasks concurrently per advisory but serializes V3 metadata fetches with a static SemaphoreSlim(1) and a Dictionary cache keyed on packageId. This avoids redundant HTTP calls when multiple advisories affect the same package while remaining safe under Task.WhenAll parallelism.Running Locally
appsettings.json:
The Microsoft Entra ID client certificate for the app registration must be installed in the
CurrentUser certificate store before running. Key Vault secrets (including the GitHub PAT) are resolved at startup via managed identity or the installed certificate.