Vulnerability Support
AvantiPoint Packages includes support for the NuGet VulnerabilityInfo v3 resource, allowing you to expose and query vulnerability information for packages in your feed.
Overview
The VulnerabilityInfo resource enables:
- Exposing known vulnerabilities for packages in your feed
- Integration with NuGet client auditing features (e.g.,
dotnet list package --vulnerable) - Querying vulnerabilities programmatically via the protocol client
Server Configuration
Vulnerability Support
Vulnerability support is enabled by default. The VulnerabilityInfo resource is always exposed in the service index to avoid NuGet client CLI warnings.
To disable vulnerability support (which will cause the endpoints to return empty results), set the EnableVulnerabilityInfo option to false in your configuration:
appsettings.json:
{
"EnableVulnerabilityInfo": false
}
Environment Variable:
export EnableVulnerabilityInfo=false
The service index will always expose a VulnerabilityInfo/6.7.0 resource. When disabled, the endpoint returns an empty vulnerability index to prevent NuGet client warnings.
Database Migrations
Before using vulnerability support, you must apply the database migrations that create the necessary tables:
For SQLite:
dotnet ef database update --context SqliteContext
For SQL Server:
dotnet ef database update --context SqlServerContext
The migrations create two tables:
VulnerabilityRecords: Stores vulnerability information (advisory URL, severity, description)PackageVulnerabilities: Maps vulnerabilities to specific packages and version ranges
Populating Vulnerability Data
Vulnerability data must be populated in the database. Currently, this must be done manually or through custom tooling.
Example: Adding a Vulnerability
using var scope = app.Services.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<IContext>();
// Create a vulnerability record
var vulnerability = new VulnerabilityRecord
{
AdvisoryUrl = "https://github.com/advisories/GHSA-xxxx-yyyy-zzzz",
Severity = "High",
Description = "SQL injection vulnerability in version 1.0.0",
CreatedUtc = DateTime.UtcNow,
UpdatedUtc = DateTime.UtcNow
};
context.VulnerabilityRecords.Add(vulnerability);
await context.SaveChangesAsync();
// Associate the vulnerability with a package
var packageVuln = new PackageVulnerability
{
PackageId = "MyPackage", // lowercase
VersionRange = "[1.0.0]", // NuGet version range syntax
VulnerabilityKey = vulnerability.Key
};
context.PackageVulnerabilities.Add(packageVuln);
await context.SaveChangesAsync();
Future Extensibility
The IVulnerabilityDataSource abstraction (optional future enhancement) would allow integration with:
- NuGet.org vulnerability feeds
- Internal security scanning systems
- Third-party vulnerability databases
Protocol Client Usage
Discovering Vulnerability Support
The protocol client automatically discovers the VulnerabilityInfo resource from the service index:
var client = new NuGetClient("https://your-feed.example.com/v3/index.json");
// The client will automatically detect if vulnerability support is available
var vulnerabilities = await client.GetPackageVulnerabilitiesAsync("MyPackage");
Querying Vulnerabilities
Get all vulnerabilities for a specific package:
var vulnerabilities = await client.GetPackageVulnerabilitiesAsync(
"MyPackage",
cancellationToken);
foreach (var vuln in vulnerabilities)
{
Console.WriteLine($"Severity: {vuln.Severity}");
Console.WriteLine($"URL: {vuln.Url}");
Console.WriteLine($"Affected versions: {vuln.Versions}");
}
Advanced Usage with IVulnerabilityClient
For more control, use the IVulnerabilityClient directly:
var factory = new NuGetClientFactory(httpClient, serviceIndexUrl);
var vulnerabilityClient = factory.CreateVulnerabilityClient();
// Get the vulnerability index
var index = await vulnerabilityClient.GetIndexOrNullAsync();
if (index != null)
{
Console.WriteLine($"Vulnerability data version: {index.Version}");
Console.WriteLine($"Number of pages: {index.Pages.Count}");
// Get a specific page
var page = await vulnerabilityClient.GetPageOrNullAsync(
index.Pages[0].Id,
cancellationToken);
}
API Endpoints
When vulnerability support is enabled, the following endpoints are available:
Vulnerability Index
URL: /v3/vulnerabilities/index.json
Returns the vulnerability index with references to vulnerability pages.
Response:
{
"version": "6.7.0",
"pages": [
{
"@id": "vulnerabilities-base.json",
"@name": "base",
"@updated": "2025-11-17T00:00:00Z"
}
]
}
Vulnerability Page
URL: Referenced in the index (e.g., /v3/vulnerabilities/vulnerabilities-base.json)
Returns vulnerability data for one or more packages.
Response:
{
"mypackage": [
{
"url": "https://github.com/advisories/GHSA-xxxx-yyyy-zzzz",
"severity": "High",
"versions": "[1.0.0, 2.0.0)"
}
]
}
Data Model
VulnerabilityRecord
Key: Unique identifier (auto-generated)AdvisoryUrl: URL to the vulnerability advisory (required, indexed)Severity: Severity level (required, max 50 characters)Description: Detailed description (optional, max 4000 characters)CreatedUtc: Creation timestampUpdatedUtc: Last update timestamp (indexed)
PackageVulnerability
Key: Unique identifier (auto-generated)PackageId: Package identifier (required, lowercase, indexed)VersionRange: NuGet version range syntax (required, max 256 characters)VulnerabilityKey: Foreign key to VulnerabilityRecord
Indexes
The following indexes are created for performance:
VulnerabilityRecords:AdvisoryUrlUpdatedUtc
PackageVulnerabilities:PackageIdPackageId + VersionRange(composite)VulnerabilityKey(foreign key)
Best Practices
- Version Ranges: Use NuGet version range syntax consistently (e.g.,
[1.0.0],[1.0.0, 2.0.0)) - Package IDs: Always store package IDs in lowercase for consistency
- Update Timestamps: Keep
UpdatedUtccurrent when modifying vulnerabilities - Severity Values: Use standard severity levels: "Low", "Moderate", "High", "Critical"
- Advisory URLs: Use canonical, permanent URLs for vulnerability advisories
Troubleshooting
Vulnerability resource not appearing in service index
- Verify
EnableVulnerabilityInfois set totruein configuration - Check application logs for startup errors
- Restart the application after configuration changes
No vulnerabilities returned
- Ensure the database migrations have been applied
- Verify vulnerability data exists in the database
- Check that package IDs are lowercase in the database
- Confirm version ranges are in valid NuGet syntax
Protocol client returns null
- The server may not support vulnerability information
- Check that the service index includes a
VulnerabilityInforesource - Ensure the HTTP client has network access to the server