Skip to content

Bulk CVE Lookup ​

Fetch the CVE List V5 record for multiple CVEs in a single request (up to 50 CVEs).

This endpoint reads CVE List V5 only. For the aggregated record (NVD, GitHub, OSV, nixpkgs security data, EPSS and KEV) use CVE Lookup; for publication badges across a list, use Batch Status.

Endpoint ​

POST /api/v1/cve/batch

Request Body ​

FieldTypeRequiredDescription
cvesstring[]YesArray of CVE IDs to look up (max 50)

Alternative Field Name

You can also use ids instead of cves for the array field name.

Response ​

json
{
  "success": true,
  "data": {
    "CVE-2024-3094": {
      "found": true,
      "status": "found",
      "data": {
        "id": "CVE-2024-3094",
        "state": "PUBLISHED",
        "datePublished": "2024-03-29T16:51:12.588Z",
        "datePublic": "2024-03-29T00:00:00.000Z",
        "dateUpdated": "2026-08-04T07:05:54.671Z",
        "dateReserved": "2024-03-29T15:38:13.249Z",
        "tags": [],
        "assignerOrgId": "53f830b8-0a3f-465b-8143-3b8a9948e749",
        "assignerShortName": "redhat",
        "ssvc": { /* ... */ },
        "adp": { /* ... */ },
        "title": "Xz: malicious code in distributed source",
        "description": "Malicious code was discovered in the upstream tarballs of xz, starting with version 5.6.0. ...",
        "severity": "critical",
        "cvssScore": 10,
        "cvssVersion": "3.1",
        "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
        "severitySource": "cna",
        "affected": [ /* ... */ ],
        "references": [ /* ... */ ],
        "problemTypes": [ { "cweId": "CWE-506", "description": "Embedded Malicious Code" } ],
        "capecs": [],
        "source": "cve-list-v5"
      },
      "sourceUrl": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2024/3xxx/CVE-2024-3094.json"
    },
    "CVE-2026-100895": {
      "found": false,
      "status": "reserved",
      "note": "The CVE Program has reserved this id for a CNA, and no record has been published for it yet."
    },
    "CVE-2099-99999": {
      "found": false,
      "status": "not_found",
      "error": "CVE not found"
    },
    "CVE-2026-2222": {
      "found": false,
      "status": "unavailable",
      "error": "CVE List API returned 503"
    }
  },
  "summary": {
    "requested": 5,
    "found": 1,
    "notFound": 1,
    "reserved": 1,
    "rejected": 0,
    "awaitingIngest": 0,
    "unavailable": 1,
    "partial": true,
    "invalidIds": ["not-a-cve"]
  },
  "timestamp": "2026-10-15T19:58:05.210Z"
}

Response Fields ​

Summary Object ​

FieldTypeDescription
requestednumberNumber of entries in the request array, including invalid ones
foundnumberCVEs with a CVE List V5 record
notFoundnumberValid CVE ids the CVE Program's own register also has no allocation for
reservednumberValid CVE ids the CVE Program's register says are RESERVED (allocated, no record published yet)
rejectednumberValid CVE ids the CVE Program's register says are REJECTED, with no CVE List V5 record ingested here yet
awaitingIngestnumberValid CVE ids listed in MITRE's recent delta feed but not yet ingested here, or confirmed PUBLISHED by the CVE Program's register but not yet ingested here
unavailablenumberValid CVE ids that could not be checked because the upstream request failed
partialbooleantrue when one or more valid CVE ids could not be checked
invalidIdsarrayEntries that are not well-formed CVE ids, as sent (only present if any)

CVE Result Object ​

FieldTypeDescription
foundbooleanWhether a CVE List V5 record was returned
statusstringfound, reserved, rejected, awaiting_ingest, not_found, or unavailable
dataobjectThe normalized CVE List V5 record (when found). Same shape as data.primary in CVE Lookup.
sourceUrlstringThe CVE List V5 JSON file for this id (when found)
notestringWhy there is no record yet (reserved, rejected, or awaiting_ingest)
errorstringWhy no record was returned (not_found or unavailable)

Non-found results ​

found: false is retained for compatibility. Read status for the answer:

  • reserved: cvelistV5 only commits a file once a record is PUBLISHED or REJECTED, so this id 404s there — but the CVE Program's own register (asked the same way CVE Lookup does) says it is RESERVED: allocated to a CNA, no record published yet.
  • rejected: the CVE Program's own register says this id is REJECTED, but no CVE List V5 record has been ingested here for it yet.
  • awaiting_ingest: either listed in MITRE's recent delta feed but this service has not ingested it yet, or the CVE Program's own register says the id is PUBLISHED but no source has ingested a record for it yet.
  • not_found: neither CVE List V5 nor the CVE Program's own register has anything for the id.
  • unavailable: the fetch, or the register check behind reserved/rejected/not_found, failed and the id was not conclusively checked. Retry it. The summary sets partial: true and counts it under unavailable, never notFound.

Record Fields ​

The commonly used fields of data:

FieldTypeDescription
idstringCVE id
statestringCVE record state, e.g. "PUBLISHED"
datePublishedstring | nullWhen the CVE Program published the record
dateUpdatedstring | nullLast update to the record
titlestringCNA-provided title
descriptionstringEnglish description
severitystringLowercase: critical, high, medium, low, or unknown
cvssScorenumberCVSS base score (0 when none is available)
cvssVersionstringCVSS version of that score
cvssVectorstringCVSS vector string
severitySourcestring | nullContainer that supplied the score: cna or an ADP container name such as cisa_adp

See CVE Lookup for the full field list. Unlike CVE Lookup, this endpoint does not fill a missing score from OSV or GitHub, so a record whose CNA and ADP containers carry no score has severity: "unknown" here.

Examples ​

Basic Request ​

bash
curl -X POST "https://api.vulnpatch.dev/api/v1/cve/batch" \
  -H "Content-Type: application/json" \
  -d '{"cves": ["CVE-2024-3094", "CVE-2021-44228", "not-a-cve", "CVE-2099-99999"]}'

Response (trimmed) ​

json
{
  "success": true,
  "data": {
    "CVE-2024-3094": {
      "found": true,
      "status": "found",
      "data": {
        "id": "CVE-2024-3094",
        "state": "PUBLISHED",
        "datePublished": "2024-03-29T16:51:12.588Z",
        "dateUpdated": "2026-08-04T07:05:54.671Z",
        "title": "Xz: malicious code in distributed source",
        "severity": "critical",
        "cvssScore": 10,
        "cvssVersion": "3.1",
        "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
        "severitySource": "cna",
        /* ... */
      },
      "sourceUrl": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2024/3xxx/CVE-2024-3094.json"
    },
    "CVE-2021-44228": {
      "found": true,
      "status": "found",
      "data": {
        "id": "CVE-2021-44228",
        "state": "PUBLISHED",
        "datePublished": "2021-12-10T00:00:00.000Z",
        "dateUpdated": "2025-10-21T23:25:23.121Z",
        "title": "Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
        "severity": "critical",
        "cvssScore": 10,
        "cvssVersion": "3.1",
        "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
        "severitySource": "cisa_adp",
        /* ... */
      },
      "sourceUrl": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2021/44xxx/CVE-2021-44228.json"
    },
    "CVE-2099-99999": {
      "found": false,
      "status": "not_found",
      "error": "CVE not found"
    }
  },
  "summary": {
    "requested": 4,
    "found": 2,
    "notFound": 1,
    "unavailable": 0,
    "partial": false,
    "invalidIds": ["not-a-cve"]
  },
  "timestamp": "2026-10-15T19:52:31.418Z"
}

Code Examples ​

javascript
async function lookupCVEs(cveIds) {
  const response = await fetch('https://api.vulnpatch.dev/api/v1/cve/batch', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ cves: cveIds })
  });

  const { data, summary } = await response.json();

  console.log(`Found ${summary.found}/${summary.requested} CVEs`);

  for (const [cveId, result] of Object.entries(data)) {
    if (result.found) {
      console.log(`${cveId}: ${result.data.severity} (CVSS ${result.data.cvssScore})`);
    } else if (result.status === 'not_found') {
      console.log(`${cveId}: no CVE List V5 record`);
    } else {
      console.log(`${cveId}: not checked (${result.error}), retry`);
    }
  }

  return data;
}

// Usage
lookupCVEs(['CVE-2024-3094', 'CVE-2021-44228']);
python
import requests

def lookup_cves(cve_ids):
    response = requests.post(
        'https://api.vulnpatch.dev/api/v1/cve/batch',
        json={'cves': cve_ids}
    )
    result = response.json()

    print(f"Found {result['summary']['found']}/{result['summary']['requested']} CVEs")

    for cve_id, cve_result in result['data'].items():
        if cve_result['found']:
            data = cve_result['data']
            print(f"{cve_id}: {data.get('severity', 'N/A')} (CVSS {data.get('cvssScore', 'N/A')})")
        elif cve_result['status'] == 'not_found':
            print(f"{cve_id}: no CVE List V5 record")
        else:
            print(f"{cve_id}: not checked ({cve_result['error']}), retry")

    return result['data']

# Usage
lookup_cves(['CVE-2024-3094', 'CVE-2021-44228'])

Error Responses ​

No CVEs Provided (400) ​

json
{
  "success": false,
  "error": "Request body must contain a \"cves\" array of CVE IDs",
  "example": { "cves": ["CVE-2024-1234", "CVE-2024-5678"] }
}

Too Many CVEs (400) ​

json
{
  "success": false,
  "error": "Maximum 50 CVEs per batch request",
  "requested": 75
}

No Valid CVE IDs (400) ​

json
{
  "success": false,
  "error": "No valid CVE IDs provided",
  "invalidIds": ["invalid-id", "also-invalid"]
}

Server Error (500) ​

json
{
  "success": false,
  "error": "Batch CVE lookup failed"
}

Notes ​

  • POST only. A GET to this path is read as a CVE id by CVE Lookup and returns 400 Invalid CVE ID format.
  • CVE IDs are case-insensitive (cve-2024-1234 works)
  • Invalid CVE IDs are skipped and reported in summary.invalidIds
  • Results are keyed by the normalized (uppercase) CVE ID; a repeated id appears once in data but is counted each time in summary.requested
  • Records are fetched live from CVE List V5 on each request
  • This endpoint is more efficient than making individual requests when you need the CVE List V5 record for multiple CVEs