# NVD CVE Vulnerability Feed (`grit-77/nvd-cves`) Actor

NVD CVE vulnerability feed for security-data research. Export vulnerability records as JSON with available scores, affected products, references and known-exploited-vulnerability fields.

- **URL**: https://apify.com/grit-77/nvd-cves.md
- **Developed by:** [Grit](https://apify.com/grit-77) (community)
- **Categories:** Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 cve records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## NVD CVE Vulnerability Feed

NVD CVE scraper returns vulnerability records with available scores, affected products, references, and KEV fields.

NVD CVE scraper uses the public source named below and writes its results to the Actor dataset.

This actor uses the [NVD CVE API 2.0](https://nvd.nist.gov/developers/vulnerabilities). CVE means Common Vulnerabilities and Exposures; CVSS is the Common Vulnerability Scoring System; CPE identifies a product and version; KEV is CISA's Known Exploited Vulnerabilities catalog.

### What it returns

Fields vary by result type and optional enrichment. The examples below are from `sample_output.json`.

| Output field | Type | Example value or excerpt from saved sample |
|---|---|---|
| `cveId` | string | `"CVE-2021-44228"` |
| `sourceIdentifier` | string | `"security@apache.org"` |
| `vulnStatus` | string | `"Analyzed"` |
| `published` | string | `"2021-12-10T10:15:09.143Z"` |
| `lastModified` | string | `"2026-08-11T19:33:44.513Z"` |
| `description` | string | `"Apache Log4j2 2.0-beta9 through 2.15.0 (excluding security releases 2.12.2, 2.12.3, and 2.3.1) JNDI…` |
| `descriptions` | array | `[{"lang": "en"}]` |
| `cvssV3` | object | `{"version": "3.1"}` |
| `cvssV3Score` | number | `10.0` |
| `cvssV3Severity` | string | `"CRITICAL"` |
| `cvssV3Vector` | string | `"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"` |
| `cvssV4` | null | `null` |
| `cvssV4Score` | null | `null` |
| `cvssV4Severity` | null | `null` |
| `cvssV4Vector` | null | `null` |
| `cvssMetrics` | array | `[{"version": "3.1"}]` |
| `kev` | boolean | `true` |
| `kevDateAdded` | string | `"2021-12-10"` |
| `kevDueDate` | string | `"2021-12-24"` |
| `kevRequiredAction` | string | `"For all affected software assets for which updates exist, the only acceptable remediation actions a…` |
| `kevVulnerabilityName` | string | `"Apache Log4j2 Remote Code Execution Vulnerability"` |
| `cwes` | array | `["CWE-20"]` |
| `affectedProducts` | array | `[{"vulnerable": true}]` |
| `configurations` | array | `[{"operator": "AND"}]` |
| `references` | array | `[{"source": "security@apache.org"}]` |
| `nvdUrl` | string | `"https://nvd.nist.gov/vuln/detail/CVE-2021-44228"` |
| `retrievedAt` | string | `"2026-10-05T11:42:41.434Z"` |
| `errors` | array | `[]` |

One row per distinct returned CVE. A malformed record or exhausted request produces an error row with an `errors` array, without a custom result charge.

| Fields | Meaning |
|---|---|
| `cveId`, `nvdUrl` | CVE identifier and official detail page |
| `description`, `descriptions` | English description when available, plus original language entries |
| `published`, `lastModified`, `retrievedAt` | UTC ISO-8601 timestamps; retrieval time records this run's freshness |
| `sourceIdentifier`, `vulnStatus` | Publishing source and NVD record status |
| `cvssV3Score`, `cvssV3Severity`, `cvssV3Vector` | Selected v3 base score, severity and vector; `null` when absent |
| `cvssV4Score`, `cvssV4Severity`, `cvssV4Vector` | Selected v4 base score, severity and vector; `null` when absent |
| `cvssV3`, `cvssV4` | Detailed assessment with version, source, type, attack vector, privileges, interaction and version-specific impact fields |
| `cvssMetrics` | Available v3/v4 assessments from all returned sources, including alternative scores |
| `kev`, `kevDateAdded`, `kevDueDate` | KEV status as reflected by NVD, date added and CISA action deadline |
| `kevRequiredAction`, `kevVulnerabilityName` | CISA action and vulnerability name supplied by NVD |
| `cwes` | Returned weakness classifications, including any NVD placeholders |
| `affectedProducts` | CPE match criteria, vulnerable flags, match IDs and version bounds |
| `configurations` | Original applicability logic, including AND/OR and negation context |
| `references` | Published reference URLs, sources and tags; linked pages are not fetched |
| `errors` | Empty for a normal record; safe error messages for failed records/requests |

For v3, the actor prefers v3.1 over v3.0. Within each version it prefers a `Primary` assessment, then NVD among assessments of equal type, then original source order. It retains alternative assessments in `cvssMetrics`; it does not compute scores or replace missing scores with zero.

### Input

```json
{
  "keyword": "log4j",
  "cvssSeverity": "CRITICAL",
  "cvssVersion": "3",
  "publishedAfter": "2021-12-01T00:00:00Z",
  "publishedBefore": "2021-12-31T23:59:59Z",
  "hasKev": true,
  "maxItems": 2
}
```

| Input | Default | Behavior |
|---|---|---|
| `keyword` | omitted | NVD description keyword search |
| `cpeName` | omitted | Full CPE 2.3 name with concrete part, vendor, product and version |
| `cvssSeverity` | omitted | `LOW`, `MEDIUM`, `HIGH` or `CRITICAL` |
| `cvssVersion` | `"3"` | Apply the severity filter to v3.x or v4.0 (`"4"`); both versions remain in output |
| `publishedAfter`, `publishedBefore` | omitted | Inclusive published-time window; both endpoints required |
| `modifiedAfter`, `modifiedBefore` | omitted | Inclusive last-modified window; both endpoints required |
| `hasKev` | `false` | `true` includes only NVD records carrying KEV data; `false` adds no KEV restriction |
| `apiKey` | omitted | Optional secret user NVD key, sent in the `apiKey` request header |
| `maxItems` | `100` | Output row cap, including error rows; range 1–100,000 |
| `pageSize` | `2000` | NVD request page size, reduced to the remaining cap; range 1–2,000 |
| `concurrency` | `1` | Fixed at one request in flight |

If no effective filter is provided, the actor searches the previous seven days by published time. Date inputs must include time and timezone, such as `2026-10-01T00:00:00Z`; each window may span at most 120 days. To search a product version, use a CPE such as `cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*`. Wildcard vendor, product or version values are rejected.

Filters combine according to NVD's API behavior. Severity filtering can match an assessment from any source; the selected primary assessment in the row can have a different severity. Inspect `cvssMetrics` for the alternatives.

### Real output example

Selected fields from `sample_output.json`, obtained by running the input above:

```json
{
  "cveId": "CVE-2021-44228",
  "published": "2021-12-10T10:15:09.143Z",
  "cvssV3Score": 10.0,
  "cvssV3Severity": "CRITICAL",
  "cvssV4Score": null,
  "kev": true,
  "kevDateAdded": "2021-12-10",
  "nvdUrl": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228",
  "errors": []
}
```

The default dataset offers overview, scoring, product and KEV views. Export JSON for nested fields or select flat fields for CSV. `RUN_SUMMARY` in the default key-value store records saved rows, CVE count, error rows, API requests, duration and whether the run stopped for its charge limit.

### Pricing

Proposed custom price: **$0.0015 per successful CVE**, or **$1.50 per 1,000 CVEs**. Errors and duplicate IDs do not trigger `cve`. Platform startup charges are separate and must be confirmed before publishing.

The proposal is 50% below the observed $0.003 CVE result event of [ryanclinton/nvd-cve-vulnerability-search](https://apify.com/ryanclinton/nvd-cve-vulnerability-search), the most used comparable NVD actor by total users in the Store API queries on 2026-10-05. See [PRICING.md](PRICING.md) for the query receipts, comparison scope and Console setup.

### Limits and reliability

Requests start at least 6.1 seconds apart, including retries, with one in flight. This conservative pacing follows [NVD's rate-limit guidance](https://nvd.nist.gov/developers/start-here) with or without a key. Transient HTTP failures and transport/JSON errors receive at most four attempts with exponential backoff and `Retry-After` handling. A server wait longer than 300 seconds becomes a clear error row instead of an early retry. Permanent HTTP errors are reported without repeated requests.

NVD pages are ordered by publication time, so a capped recent-week query returns the earliest matching records in that week. There is no automatic splitting of windows longer than 120 days or persisted pagination checkpoint. NVD updates during pagination can affect completeness; IDs are deduplicated within the run. Error rows consume the row cap. Increase `maxItems` or narrow the search when a query exceeds the cap.

NVD records can lack scoring, product details or KEV data. A false KEV flag means NVD did not supply KEV membership in that response; it does not establish that a vulnerability has never been exploited. Product applicability logic is retained because a flattened CPE list alone does not establish that a deployed system is vulnerable.

### FAQ

**What limits a search?** `maxItems` caps distinct CVE and error rows. Date-window filters must stay within the schema’s allowed span.

**Do I need a proxy, login, or API key?** No key is required; an optional personal NVD key can be supplied. The actor does not configure a proxy.

**How is it priced?** The proposed pay-per-event model charges `cve` for each distinct successfully saved CVE. Errors, duplicates, and empty searches have no custom event charge.

**How are NVD rate limits handled?** The client sends requests sequentially with a minimum interval and retries temporary failures. A long `Retry-After` beyond its budget stops the request.

**How fresh is vulnerability data?** `published` and `lastModified` are NVD source timestamps; `retrievedAt` records this fetch. Re-run a modified-date search to see later source changes.

**Why is a CVSS score absent?** NVD may omit that version or publish several assessments. Inspect `cvssMetrics` and the source record.

### Use with AI agents / MCP

After the owner publishes it, call this actor through Apify's API or the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp). Use small `maxItems` values for an agent request, keep the NVD links as evidence, and check `errors` before using a record. Prefer `cvssV3Score`/`cvssV4Score` for sorting and retain metric sources and applicability logic for interpretation. No model calls are made by the actor.

### Local development

Runtime dependencies are `apify` and `httpx`; tests use the existing `pytest`. No additional package installation was required.

From this directory, run unit tests and the separately marked live smoke test:

```powershell
C:/GritWork/earn/.venv/Scripts/python.exe -m pytest tests --ignore=tests/test_live.py -q -p no:cacheprovider
C:/GritWork/earn/.venv/Scripts/python.exe -m pytest tests/test_live.py -m live -q -p no:cacheprovider
```

The helper below writes `storage/key_value_stores/default/INPUT.json`, sets `APIFY_LOCAL_STORAGE_DIR`, and launches the same Python as `python -m src`, without the Apify CLI. Use a fresh storage path each time:

```powershell
C:/GritWork/earn/.venv/Scripts/python.exe tools/local_run.py --input examples/log4j_kev.json --storage storage/new-run --output sample_output.json
```

Local pay-per-event charges are simulated by the SDK; the SDK's fallback test prices are not the proposed Store prices. The real sample contains two CVEs. Test and run receipts are in `evidence/` and the ignored local `storage/` directories. The Docker image and Apify cloud build have not been exercised in this delivery.

# Actor input Schema

## `keyword` (type: `string`):

Search NVD CVE descriptions. Multiple words follow NVD keyword-search semantics.

## `cpeName` (type: `string`):

Full 13-component CPE name. Part, vendor, product and version must be concrete, for example cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:\*.

## `cvssSeverity` (type: `string`):

NVD severity filter for the chosen CVSS version. Matches any supplied assessment; the selected primary score in the output can differ.

## `cvssVersion` (type: `string`):

Choose the score version used by the severity filter. Output includes both v3 and v4 when present.

## `hasKev` (type: `boolean`):

True adds the NVD hasKev filter for CISA KEV catalog entries. False includes records regardless of KEV status.

## `apiKey` (type: `string`):

Your own NVD API key. Sent only in the apiKey HTTP header. Requests are conservatively paced with or without a key.

## `maxItems` (type: `integer`):

Hard cap including error rows; successful distinct CVEs trigger the cve event.

## `pageSize` (type: `integer`):

Records requested per NVD page, automatically reduced to the remaining row cap.

## `concurrency` (type: `integer`):

Fixed at one request in flight to respect NVD rate limits.

## `publishedAfter` (type: `string`):

Inclusive ISO-8601 timestamp with timezone, such as 2026-10-01T00:00:00Z. Supply both endpoints of this window. Maximum span: 120 days.

## `publishedBefore` (type: `string`):

Inclusive ISO-8601 timestamp with timezone, such as 2026-10-01T00:00:00Z. Supply both endpoints of this window. Maximum span: 120 days.

## `modifiedAfter` (type: `string`):

Inclusive ISO-8601 timestamp with timezone, such as 2026-10-01T00:00:00Z. Supply both endpoints of this window. Maximum span: 120 days.

## `modifiedBefore` (type: `string`):

Inclusive ISO-8601 timestamp with timezone, such as 2026-10-01T00:00:00Z. Supply both endpoints of this window. Maximum span: 120 days.

## Actor input object example

```json
{
  "keyword": "log4j",
  "cvssVersion": "3",
  "hasKev": false,
  "maxItems": 100,
  "pageSize": 2000,
  "concurrency": 1
}
```

# Actor output Schema

## `dataset` (type: `string`):

Download the default dataset containing CVE vulnerability records and error rows.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keyword": "log4j"
};

// Run the Actor and wait for it to finish
const run = await client.actor("grit-77/nvd-cves").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "keyword": "log4j" }

# Run the Actor and wait for it to finish
run = client.actor("grit-77/nvd-cves").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keyword": "log4j"
}' |
apify call grit-77/nvd-cves --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,grit-77/nvd-cves"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0cdhLDUgiGAVwzcUm/builds/SDBp89YQoecZ7AC6d/openapi.json
