# CVE Vulnerability Monitor (NVD, CISA KEV and EPSS) (`nightwave-owner/vulnerability-monitor-nvd-kev-epss`) Actor

CVE records from NVD with CVSS score, CWE and affected vendors, joined with CISA KEV exploitation status and FIRST EPSS exploit probability in one row. Filter by keyword, vendor, CVSS, KEV and EPSS, and use onlyNew for daily vulnerability monitoring.

- **URL**: https://apify.com/nightwave-owner/vulnerability-monitor-nvd-kev-epss.md
- **Developed by:** [Viktor Wiberg](https://apify.com/nightwave-owner) (community)
- **Categories:** Developer tools, AI, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 vulnerabilities

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

## CVE Vulnerability Monitor (NVD, CISA KEV and EPSS)

Three public sources answer three different questions about a vulnerability. The National Vulnerability Database (NVD) at NIST describes the CVE: what is affected, the CVSS severity and the weakness type (CWE). The CISA Known Exploited Vulnerabilities catalog (KEV) says whether attackers are already using it. FIRST's Exploit Prediction Scoring System (EPSS) estimates the probability that it will be exploited in the next 30 days.

This actor reads all three and returns one row per CVE with the answers side by side. Use it to triage new CVEs for the vendors you run, to feed a ticketing system or a SIEM with the CVEs that matter, to check a list of CVE ids from a scanner report against KEV and EPSS, or to get a daily list of newly exploited vulnerabilities.

### Example from a real run

Run `7CBEPmpa58WX6YhqJ` on Apify on 4 October 2026, with this input: Fortinet and Cisco CVEs that CISA added to KEV since 1 July 2026.

```json
{
  "vendors": ["fortinet", "cisco"],
  "dateField": "kevDateAdded",
  "publishedFrom": "2026-07-01",
  "onlyNew": true
}
```

It returned 12 CVEs in 4 seconds of run time, newest KEV addition first. The first two rows from the dataset, with `source`, `license` and `retrievedAt` left out here to keep it short:

```json
[
  {
    "cveId": "CVE-2026-104286",
    "published": "2026-10-01T20:17:24.010Z",
    "lastModified": "2026-10-02T12:35:33.990Z",
    "vulnStatus": "Analyzed",
    "description": "An improper limitation of a pathname to a restricted directory ('path traversal') vulnerability in Fortinet FortiMail 8.0.0 through 8.0.1, FortiMail 7.6.0 through 7.6.6, FortiMail 7.4.0 through 7.4.8, FortiMail 7.2.0 through 7.2.9 may allow an unauthenticated attacker to write arbitrary files on the underlying system via crafted HTTP or HTTPS requests.",
    "cvssScore": 9.8,
    "cvssSeverity": "CRITICAL",
    "cvssVersion": "3.1",
    "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
    "cwe": ["CWE-22"],
    "affectedVendors": ["Fortinet"],
    "affectedProducts": ["FortiMail"],
    "inKev": true,
    "kevDateAdded": "2026-10-01",
    "kevDueDate": "2026-10-04",
    "kevRansomware": "Unknown",
    "epssScore": 0.02201,
    "epssPercentile": 0.81912,
    "epssDate": "2026-10-03",
    "references": [
      "https://fortiguard.fortinet.com/psirt/FG-IR-26-175",
      "https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-104286"
    ],
    "nvdUrl": "https://nvd.nist.gov/vuln/detail/CVE-2026-104286"
  },
  {
    "cveId": "CVE-2026-76504",
    "published": "2026-09-30T13:17:20.247Z",
    "lastModified": "2026-10-03T00:16:39.140Z",
    "vulnStatus": "Analyzed",
    "description": "A vulnerability in the API session-based authentication management of Cisco Catalyst SD-WAN Manager could allow an unauthenticated, remote attacker to access an affected system with privileges of the admin user. ...",
    "cvssScore": 9.8,
    "cvssSeverity": "CRITICAL",
    "cvssVersion": "3.1",
    "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
    "cwe": ["CWE-177"],
    "affectedVendors": ["Cisco"],
    "affectedProducts": ["Cisco Catalyst SD-WAN Manager", "catalyst_sd-wan_manager"],
    "inKev": true,
    "kevDateAdded": "2026-09-30",
    "kevDueDate": "2026-10-03",
    "kevRansomware": "Unknown",
    "epssScore": 0.01575,
    "epssPercentile": 0.74593,
    "epssDate": "2026-10-03",
    "references": [
      "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-sdwan-webauth-xr8beuuU",
      "https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-76504"
    ],
    "nvdUrl": "https://nvd.nist.gov/vuln/detail/CVE-2026-76504"
  }
]
```

The same input run again right after (run `ld73F8NhhS2AHtQdI`) returned 0 CVEs, since nothing new had been added in between. See "Monitoring and scheduling".

With empty input the actor returns the CVEs published in the last 7 days that have a CVSS score of 7 or higher and are in KEV or have an EPSS score above 0.1. In a test on 4 October 2026 (run `aHLIDq7Yb5iq8k5BH`) it read 2 571 CVEs from NVD and returned the 7 that met this, in 3 seconds of run time.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `keywords` | array | | Product or vendor names searched in NVD, for example `OpenSSL`. Each keyword is one search. Several words in one keyword must all appear in the CVE. |
| `cveIds` | array | | CVE ids to look up directly, for example `CVE-2024-3400`. The date window does not apply. Up to 200 per run. |
| `vendors` | array | | Keep only CVEs that affect these vendors. Matched against the affected vendors, ignoring case and punctuation, so `dlink` matches `D-Link`. |
| `cvssMin` | number | | Lowest CVSS base score, 0 to 10. |
| `kevOnly` | boolean | `false` | Keep only CVEs in the CISA KEV catalog. |
| `epssMin` | number | | Lowest EPSS score, 0 to 1. `0.1` means at least a 10 % estimated probability of exploitation in the next 30 days. |
| `publishedFrom`, `publishedTo` | string | last 7 days | Date window, `YYYY-MM-DD`. Windows longer than 120 days are read in parts, since NVD allows at most 120 days per request. |
| `dateField` | string | `published` | Which date the window applies to: `published`, `lastModified` (changed by NVD, for example a new CVSS score) or `kevDateAdded` (added to KEV). |
| `maxResults` | integer | `50` | Maximum number of CVEs, newest first. 1 to 10 000. |
| `onlyNew` | boolean | `false` | Return only CVEs not delivered before for the same input. See "Monitoring and scheduling". |

The filters combine. With only `vendors`, each vendor is searched as a keyword and then checked against the affected vendors. With `keywords` and `vendors` both set, the keywords are searched and the vendors filter the result. When none of `keywords`, `cveIds`, `vendors`, `cvssMin`, `kevOnly` and `epssMin` is set, the default filter described above applies. Set `cvssMin` to `0` to get every CVE in the window instead.

Example input: high and critical OpenSSL CVEs published this year.

```json
{
  "keywords": ["OpenSSL"],
  "cvssMin": 7,
  "publishedFrom": "2026-01-01"
}
```

Example input: check CVE ids from a scanner report against KEV and EPSS.

```json
{
  "cveIds": ["CVE-2024-3400", "CVE-2021-44228", "CVE-2023-4966"]
}
```

### Output

| Field | Description |
|---|---|
| `cveId` | The CVE id |
| `published`, `lastModified` | When the CVE was published in NVD and last changed, UTC |
| `vulnStatus` | NVD's analysis status, for example `Analyzed`, `Awaiting Analysis` or `Deferred` |
| `description` | English description, at most 500 characters |
| `cvssScore`, `cvssSeverity`, `cvssVersion`, `cvssVector` | CVSS base score. Version 3.1 is used when it exists, then 3.0, 4.0 and 2.0, and NVD's own score before the one from the CVE's issuer |
| `cwe` | Weakness types, for example `["CWE-22"]` |
| `affectedVendors`, `affectedProducts` | From the CVE record and from NVD's CPE data, up to 20 each. Products can appear twice, once by the issuer's name and once by the CPE name |
| `inKev` | `true` when the CVE is in the CISA KEV catalog |
| `kevDateAdded`, `kevDueDate` | When CISA added it, and the remediation deadline for US federal agencies |
| `kevRansomware` | CISA's `knownRansomwareCampaignUse`: `Known` or `Unknown`. `null` when not in KEV |
| `epssScore`, `epssPercentile`, `epssDate` | EPSS probability (0 to 1), its percentile among all scored CVEs and the date of the score. `null` when FIRST has not scored the CVE yet |
| `references` | Up to 5 links, vendor advisories and patches first |
| `nvdUrl` | The CVE's page at NVD |
| `source`, `license`, `retrievedAt` | Attribution and the time of the run |

### Monitoring and scheduling

Set `onlyNew` to `true` to run the same search on a schedule. The actor then remembers which CVEs it has delivered for that input, in a named key-value store in your Apify account (`nightwave-state-vulnerability-monitor-nvd-kev-epss`, one record per input). Each run returns and charges only CVEs not delivered before. A CVE comes once more on the day CISA adds it to KEV, so a CVE you saw as unexploited is reported again when it becomes exploited. The first run returns everything in the selection. A run without news finishes successfully with 0 rows.

The default date window moves with each run (the last 7 days), and `onlyNew` and `maxResults` are not part of the remembered input, so a daily run with the same fields keeps its state. Changing any other field starts a fresh state. To start over with the same input, delete the record in the key-value store.

Example: every morning at 07:00 Swedish time, list CVEs that CISA has added to KEV for the vendors in your network. In Apify Console, open **Schedules**, create a schedule with the cron expression `0 7 * * *` and add this actor with the input below.

```json
{
  "vendors": ["fortinet", "cisco", "ivanti", "citrix"],
  "dateField": "kevDateAdded",
  "onlyNew": true
}
```

The same schedule through the Apify API:

```sh
curl -X POST "https://api.apify.com/v2/schedules?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"name": "daily-kev-check", "cronExpression": "0 7 * * *", "timezone": "Europe/Stockholm", "isEnabled": true, "isExclusive": true,
       "actions": [{"type": "RUN_ACTOR", "actorId": "nightwave-owner~vulnerability-monitor-nvd-kev-epss",
                    "runInput": {"contentType": "application/json; charset=utf-8", "body": "<the input above as a JSON string>"}}]}'
```

Add an Apify integration (email, Slack or a webhook) on the schedule to be told when a run has rows.

### Limits

- **NVD's rate limit is followed.** Without an API key NVD allows 5 requests in a rolling 30 second window. The actor keeps under that and waits and retries when NVD answers 403 or 429. A page holds 2 000 CVEs, so a week of all new CVEs takes 2 requests, while 20 keywords over a year take 60 requests and about 6 minutes. Each CVE id in `cveIds` is one request, so 200 ids take about 20 minutes.
- At most 60 NVD pages (120 000 CVEs) are read per run. For more, split the date window.
- The keyword search is NVD's: it matches words in the description. A vendor that is only named in CPE data and not in the text can be missed while NVD has not analyzed the CVE yet.
- Many new CVEs wait weeks for NVD's analysis (`Awaiting Analysis` or `Deferred`). They still have the issuer's CVSS score in most cases, and the actor uses it. A CVE without any score is left out when `cvssMin` is set.
- EPSS scores new CVEs within a few days. Until then `epssScore` is `null`.
- Rejected CVEs are always left out.
- Requests are retried three times on network errors, rate limits and server errors. If the KEV catalog cannot be read, KEV status comes from NVD's own KEV fields and `kevRansomware` is `null`. If EPSS cannot be read and no EPSS filter is set, the rows are returned with `epssScore` `null`.

The data is information about published vulnerabilities. It is not a security assessment of your systems: whether a CVE affects you depends on the versions and configuration you run.

### Source and license

- **NVD** ([NVD API 2.0](https://nvd.nist.gov/developers/vulnerabilities), `https://services.nvd.nist.gov/rest/json/cves/2.0`), published by NIST. NVD data is US government information and not subject to copyright in the United States. NVD's terms ask products to state: "This product uses the NVD API but is not endorsed or certified by the NVD."
- **CISA KEV** ([catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog), `known_exploited_vulnerabilities.json`). CISA: "The KEV database is distributed under the Creative Commons 0 1.0 License."
- **EPSS** from FIRST ([API](https://api.first.org/data/v1/epss)). FIRST: "EPSS scores are published freely via CSV download and API with no registration required" and "Attribution is requested when EPSS data is used in publications or products."

Every row carries `source` and `license` so you can credit the sources. This actor is not affiliated with or endorsed by NIST, CISA or FIRST.

### Pricing

Pay per event: 0.005 USD per CVE returned (event `vulnerability`), which is 5.00 USD per 1 000 CVEs. Apify platform usage for the run comes on top and is small, since the actor only makes API requests. A run without matches costs nothing per CVE, and with `onlyNew` you pay only for CVEs you have not received before. `maxResults` caps how many CVEs, and therefore how much, a run can charge.

Rows are delivered only after they have been charged. If you set a maximum cost per run (maxTotalChargeUsd), the run stops there and its status message says how many rows were delivered.

### Contact

Built and maintained by Nightwave AB. Questions, bugs and feature requests: kontakt@nightwave.se

### På svenska

Actorn hämtar sårbarheter (CVE) från NVD och lägger till två saker per CVE: om den finns i CISA:s katalog över sårbarheter som redan utnyttjas (KEV) och FIRST:s EPSS-värde, sannolikheten att den utnyttjas inom 30 dagar. Resultatet är en rad per CVE.

- Fält: CVE-id, publicerad och ändrad, NVD:s status, beskrivning (högst 500 tecken), CVSS-poäng, allvarlighetsgrad, version och vektor, CWE, berörda leverantörer och produkter, KEV-datum och åtgärdsfrist, känd användning i ransomware, EPSS-värde och percentil, upp till fem länkar och länk till NVD.
- Filter: sökord, CVE-id, leverantörer, lägsta CVSS, bara KEV, lägsta EPSS och datumintervall (publicerad, ändrad eller tillagd i KEV). Standard är 50 rader och de senaste 7 dagarna.
- Tom input: CVE från senaste veckan med CVSS 7 eller högre som finns i KEV eller har EPSS över 0,1.
- Bevakning: med `onlyNew` kommer actorn ihåg vilka CVE den redan har levererat för samma input (key-value store `nightwave-state-vulnerability-monitor-nvd-kev-epss`). Varje körning levererar och debiterar bara nya, och en CVE kommer en gång till när CISA lägger till den i KEV. Lägg actorn på ett dagligt schema i Apify under Schedules, se avsnittet "Monitoring and scheduling".
- Actorn följer NVD:s gräns på 5 anrop per 30 sekunder utan nyckel.
- Datan är information om publicerade sårbarheter, inte en säkerhetsbedömning av dina system.
- Källor: NVD (NIST, amerikansk offentlig information), CISA KEV (CC0 1.0) och EPSS (FIRST, fri att använda med källhänvisning).
- Pris: 0,005 USD per CVE (5,00 USD per 1 000), plus Apifys plattformsanvändning.
- Kontakt: kontakt@nightwave.se

# Actor input Schema

## `keywords` (type: `array`):

Product or vendor names to search for in NVD, for example \["OpenSSL"]. Each keyword is one search, and several words in one keyword must all appear. Empty means all CVEs in the date window.

## `cveIds` (type: `array`):

CVE ids to look up directly, for example \["CVE-2024-3400"]. The date window is ignored for these. Up to 200 per run.

## `vendors` (type: `array`):

Keep only CVEs that affect these vendors, for example \["fortinet", "cisco"]. Matched against the affected vendors, ignoring case and punctuation.

## `cvssMin` (type: `number`):

Keep only CVEs with a CVSS base score at or above this, 0 to 10, for example 7 for high and critical. CVEs without a score are left out when this is above 0.

## `kevOnly` (type: `boolean`):

Keep only CVEs in the CISA Known Exploited Vulnerabilities catalog, for example true. Defaults to false.

## `epssMin` (type: `number`):

Keep only CVEs whose EPSS probability of exploitation in the next 30 days is at or above this, 0 to 1, for example 0.1. CVEs without an EPSS score yet are left out when this is above 0.

## `publishedFrom` (type: `string`):

Start of the date window, YYYY-MM-DD, for example "2026-09-01". Defaults to 7 days before the end date. Longer windows are read in 120 day parts.

## `publishedTo` (type: `string`):

End of the date window, YYYY-MM-DD, for example "2026-09-30". Defaults to now.

## `dateField` (type: `string`):

Which date the window filters on: published (when the CVE was published), lastModified (when NVD last changed it) or kevDateAdded (when CISA added it to KEV). Defaults to published. Use kevDateAdded to watch for newly exploited CVEs of any age.

## `maxResults` (type: `integer`):

Maximum number of CVEs to return, newest first, for example 50. Each CVE is one billable result. 1 to 10 000, defaults to 50.

## `onlyNew` (type: `boolean`):

For scheduled runs. When true, CVEs that an earlier run with the same input already delivered are skipped and not charged. A CVE comes once more when CISA adds it to KEV. The first run returns everything in the selection. Defaults to false.

## Actor input object example

```json
{
  "keywords": [
    "OpenSSL",
    "Apache Tomcat"
  ],
  "cveIds": [
    "CVE-2024-3400",
    "CVE-2021-44228"
  ],
  "vendors": [
    "fortinet",
    "cisco"
  ],
  "cvssMin": 7,
  "kevOnly": true,
  "epssMin": 0.1,
  "publishedFrom": "2026-09-01",
  "publishedTo": "2026-09-30",
  "dateField": "kevDateAdded",
  "maxResults": 50,
  "onlyNew": true
}
```

# Actor output Schema

## `results` (type: `string`):

One row per CVE with CVSS, KEV and EPSS, as JSON. Open in Apify Console or download via the dataset API.

# 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 = {
    "keywords": [],
    "cveIds": [],
    "vendors": [],
    "kevOnly": false,
    "dateField": "published",
    "maxResults": 50,
    "onlyNew": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("nightwave-owner/vulnerability-monitor-nvd-kev-epss").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 = {
    "keywords": [],
    "cveIds": [],
    "vendors": [],
    "kevOnly": False,
    "dateField": "published",
    "maxResults": 50,
    "onlyNew": False,
}

# Run the Actor and wait for it to finish
run = client.actor("nightwave-owner/vulnerability-monitor-nvd-kev-epss").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 '{
  "keywords": [],
  "cveIds": [],
  "vendors": [],
  "kevOnly": false,
  "dateField": "published",
  "maxResults": 50,
  "onlyNew": false
}' |
apify call nightwave-owner/vulnerability-monitor-nvd-kev-epss --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nightwave-owner/vulnerability-monitor-nvd-kev-epss"
        }
    }
}
```

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/9NakyGhBA5LQ1VUHs/builds/zgeUXcP903QfFeelU/openapi.json
