NVD API Compatibility

What changes

Where VulnCheck adds coverage, corrects values, and how to read source and type

Responses are schema-valid NVD 2.0. The data inside them is not always identical to NVD's, because VulnCheck fills gaps and corrects values. This page covers where that happens and how to read it.

Where coverage is added

FieldWhat VulnCheck adds
metricsCVSS scores for CVEs NVD has not scored, and VulnCheck's own score where it disagrees with NVD's
weaknessesA real CWE where NVD has NVD-CWE-noinfo or NVD-CWE-Other, and a corrected CWE where VulnCheck disagrees
vcConfigurationsCPE configurations for CVEs NVD has not yet analysed (see CPE data)

Reading source and type

metrics and weaknesses are multi-source arrays: one entry per provider, each carrying a source and a type. When VulnCheck corrects a value, VulnCheck's entry becomes type: Primary and NVD's original is retained as type: Secondary.

Nothing is deleted. NVD's exact original value is always still in the response.

There are four cases:

CaseResult
VulnCheck has no valueNVD's entry passes through unchanged
VulnCheck agrees with NVDNVD's entry passes through unchanged; the duplicate is dropped
VulnCheck disagrees with NVDVulnCheck is Primary, NVD is retained as Secondary
NVD has no valueVulnCheck's entry stands alone as Primary

Entries from any other provider; a CNA's own CVSS, CISA-ADP — pass through with their original source and type untouched.

A corrected metric

{
  "metrics": {
    "cvssMetricV31": [
      {
        "source": "disclosure@vulncheck.com",
        "type": "Primary",
        "cvssData": { "baseScore": 9.8, "baseSeverity": "CRITICAL" }
      },
      {
        "source": "nvd@nist.gov",
        "type": "Secondary",
        "cvssData": { "baseScore": 7.5, "baseSeverity": "HIGH" }
      }
    ]
  }
}

Read only the Primary entry and you get the corrected value. Read source: nvd@nist.gov and you get NVD's exact original.

The Primary-label semantic shift

On a literal NVD response, type: Primary always means NVD's own value. On these endpoints, a corrected field's Primary is VulnCheck's value. Code that treats Primary as "NIST authoritative" will silently read a different number.

If that distinction matters to you, key on source, not type:

  • source: nvd@nist.gov - NVD's value, always, whatever its type says
  • source: disclosure@vulncheck.com - VulnCheck's value

disclosure@vulncheck.com resolves through /rest/json/source/2.0 like any other source identifier.

CPE data

Three fields carry CPE data, and they are kept separate rather than merged.

configurations
array
NVD's own CPE configurations, passed through verbatim. Never modified, never supplemented.
vcConfigurations
array
VulnCheck's CPE analysis, in the same shape as configurations. Present on a large share of recent CVEs, including many where NVD's configurations is null.
vcVulnerableCPEs
array
A flat list of the vulnerable CPE strings from vcConfigurations. A convenience projection, not an independent source — do not treat it as separate evidence. Returned only when you ask for it with the vcVulnerableCPEs parameter. See Requesting vcVulnerableCPEs.

If you want only NVD-official CPE data, read configurations and ignore the other two. That is the whole answer to whether these fields can affect your existing matching: they cannot, unless you opt in.

Both added fields are omitted when empty, so has("vcConfigurations") is a valid presence test.

Requesting vcVulnerableCPEs

vcConfigurations is returned by default. vcVulnerableCPEs is not: add vcVulnerableCPEs to the query to include it. Like hasKev, it is a flag, so the parameter alone turns it on, vcVulnerableCPEs=true does the same, and vcVulnerableCPEs=false leaves it off.

curl "https://api.vulncheck.com/rest/json/cves/2.0?cveId=CVE-2021-44228&vcVulnerableCPEs" \
  -H "apiKey: {vulncheck-api-key}"

It is off by default because of its size. It expands every range in vcConfigurations into individual CPE strings, which can mean more than 10,000 entries on a single CVE, and across a full page it is most of the response. An unmodified NVD client gets pages of roughly the size it gets from NVD, and still receives VulnCheck's CPE analysis in vcConfigurations. vcVulnerableCPEs adds no separate assessment, only the expanded list.

If you opt in, use a smaller resultsPerPage than the default 2,000.

What to know before using vcConfigurations

  1. These CPEs are analyst-derived and are not validated against the NVD CPE dictionary. They may name a vendor or product NVD has not minted. Measured against NVD's own eventual output on CVEs published in 2024 Q1, VulnCheck's CPEs agreed exactly 90% of the time and at vendor:product level 98% of the time. Where they differ it is usually a genuine naming disagreement.
  2. matchCriteriaId is absent. NVD mints those UUIDs for its own match criteria; a VulnCheck-derived entry has none, so the field is omitted. Do not use it as a join key against /rest/json/cpematch/2.0 for these entries.
  3. VulnCheck entries can be broader than NVD's. Where NVD splits a version range across edition-qualified entries, VulnCheck may emit a single entry with edition:* covering the same range — same coverage, wider match. If you match on edition, prefer configurations where it is populated.

Why CPE data is separate when metrics are layered

Metrics and weaknesses use the Primary/Secondary layering described above. CPE data does not, it lives in its own fields and is never merged into configurations.

That is a schema constraint rather than a preference: cpe_match in NVD's schema requires matchCriteriaId, and VulnCheck-derived entries have no NVD match criteria to reference. Merging them would produce a response that fails NVD's own validation.

Schema validity

Responses validate against NVD's published schemas from csrc.nist.gov. vcConfigurations and vcVulnerableCPEs are additive fields on the CVE object, which NVD's schema permits — it does not set additionalProperties: false there.

The response envelope is a different matter: NVD closes it, so it carries exactly the seven keys NVD emits and nothing else. The one exception is opt-in (see Pagination).