Vulnerability information

NuGet client, starting from version 6.7, can download known package vulnerability information to use in scenarios such as checking packages during restore operations. While the package metadata resource also contains known vulnerability information, if an app needs to check a large number of packages for known vulnerabilities, it's much faster to download a file of known vulnerabilities and lookup locally, rather than making a large number of HTTP requests. For example, this enables NuGet Restore to quickly check restored packages for known vulnerabilities, which historically never downloaded package details from the package metadata resource.

The API consists of at least two files, the vulnerability index and one or more vulnerability page files. Known vulnerability data can be partitioned into multiple files, and the vulnerability index provides clients with information needed to cache files, and update the cache, efficiently.

The resource used for building this URL is the VulnerabilityInfo resource found in the service index.

Suggested partitioning strategy

The pages listed in the vulnerability index should ideally be optimized to maximize caching, and therefore minimize updates to large files. This will allow clients to minimize the frequency it needs to download updates.

A suggested strategy for vulnerability data partitioning is to have two pages, base.json and updates.json. The base.json file is updated periodically (for example once a month), and contains all known vulnerabilities at the time the file is regenerated. The updates.json file should contain any new advisories published since base.json was last regenerated. This will allow clients to download the large base.json infrequently, while the frequently changing updates.json file is always relatively small.

NuGet clients combine the data from multiple files additively, and may load the files in any order. The data file schema does not allow for modification or redaction of known vulnerability from another file. Therefore if a server's vulnerability data source (for example the GitHub Advisories Database) modifies an existing advisory, the NuGet server must modify the page that the vulnerability information was previously reported. One way to achieve this with the suggested partition scheme is to treat all vulnerability modifications and deletions as a trigger to regenerate the complete base.json file, and empty updates.json.

Versioning

The following @type values are used:

@type value Notes
VulnerabilityInfo/6.7.0 The initial release

Vulnerability index

The vulnerability index is a JSON array of objects with the following properties:

Name Type Required Notes
@name string yes A short name for the file, used as a cache key.
@id string yes The full (absolute) URL to a vulnerability data file.
@updated string yes An ISO 8601 string representing the date and time the file was last updated, ideally with the UTC timezone.
comment string no A optional descriptive string.

The following restrictions apply:

  • The index must be an array of objects with between 1 and 16 items. If the server does not have any vulnerability data (zero pages), then must remove the VulnerabilityInfo resource from the ServiceIndex.
  • @name must be unique within the index, must be between 1 and 32 characters long, and can only use the characters A to Z, a to z, 0 to 9, -, or _.
  • @id must be an absolute URL, not a relative URL.

Vulnerability page

Vulnerability page files are a JSON object used as a dictionary. Property keys are the lower-case package id and property values are an array of the following object with the following properties:

Name Type Required Notes
severity integer yes 0 means low, 1 means medium, 2 means high, 3 means critical.
url string yes URL where users can get more information about the vulnerability.
versions string yes The version range that is vulnerable, using NuGet's version range syntax.

Package IDs (the root object's keys) must be lowercased with String.ToLowerInvariant.

The list of known vulnerabilities for a package should be sorted in descending order of the max version of the version range, followed by descending version of the min version, followed by the ascending order of the URL. Ranges with null min or max versions (unbounded) in a version range should be sorted to before non-null (bounded) versions.

An empty page, one that does not provide any known vulnerabilities, must be an empty JSON array ([]).

Samples

Here is a sample of a vulnerability index:

[
    {
        "@name": "base",
        "@id": "https://nuget.contoso.com/v3/vulnerabilities/3bb6b300-2f74-45bc-af06-746fd21c024b.json",
        "@updated": "2023-06-01T06:14:58.4159909Z",
        "comment": "The base data for vulnerability update periodically"
    },
    {
        "@name": "update",
        "@id": "https://nuget.contoso.com/v3/vulnerabilities/ffd572cd-33f3-4372-8714-a9cab2e86b45.json",
        "@updated": "2023-06-14T11:35:30.3155764Z",
        "comment": "The patch data for the vulnerability. Contains all the vulnerabilities since base was last updated."
    }
]

Here is a sample of a vulnerability data file:

{
    "contoso.library": [
        {
            "url": "https://cve.contoso.com/advisories/1",
            "severity": 1,
            "versions": "(, 2.0.0)"
        },
        {
            "url": "https://cve.contoso.com/advisories/2",
            "severity": 2,
            "versions": "(1.0.0, 2.0.0)"
        }
    ],
    "contoso.utilities": [
        {
            "url": "https://cve.contoso.com/advisories/3",
            "severity": 3,
            "versions": "(, 1.0.0)"
        }
    ]
}