# CISA KEV Watchlist Monitor - Catalog Changes and EPSS (`maydit/cisa-kev-watchlist-monitor`) Actor

Monitor CISA known exploited vulnerability watchlists by vendor, product or CVE. Track saved catalog revisions, exact match evidence and optional FIRST EPSS scores. No API key.

- **URL**: https://apify.com/maydit/cisa-kev-watchlist-monitor.md
- **Developed by:** [Brandt May](https://apify.com/maydit) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 vulnerability observations

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

![Known vulnerabilities, scoped to you — illustrative workflow](https://api.apify.com/v2/key-value-stores/YGxD9JRpduom8Q5Zd/records/cisa-kev-watchlist-monitor-6bc9e258e294.png?signature=1NcEedp70Z3kVKxT3irOx)

### Known vulnerabilities, scoped to you

Turn the CISA Known Exploited Vulnerabilities catalog into a repeatable watchlist for security research and service-desk workflows. Saved observations retain published actions, exact match evidence and optional source-dated FIRST EPSS scores.

[Open this Actor in Console](https://console.apify.com/actors/maBtzREXN4v3DFSGW/input) · [First run](#try-this-actor) · [Results](#result-preview) · [Cost](#usage-and-pricing) · [Full guide](#full-guide)

### Try this Actor

1. **Choose a small scope.** Use the existing **Microsoft Exchange KEV watchlist** example below: vendor Microsoft, product Exchange and at most five saved observations. Leave EPSS and comparison off unless you need them.
2. **Run and review.** Open the dataset for CVE rows and the run's key-value-store `SUMMARY` for catalog coverage, filtering and enrichment status. `epssStatus` distinguishes absent or unavailable enrichment.
3. **Use the results.** Export JSON for nested match evidence and EPSS values, or CSV for the main catalog fields. Use official source links when reviewing required actions.

**Read this before using the data:** A watchlist match does not establish exposure of your installed assets. Catalog absence is not proof of safety. CISA's published due date retains its original context; it is not a deadline calculated for your organization.

**Microsoft Exchange KEV watchlist** — copy this input into the JSON editor in Console.

```json
{
  "vendors": [
    "Microsoft"
  ],
  "products": [
    "Exchange"
  ],
  "maxResults": 5
}
```

### Result preview

The dataset view highlights these columns:

- **CVE ID** · `cveId`
- **Vulnerability title** · `title`
- **Published vendor** · `vendor`
- **Published product** · `product`
- **Added to KEV** · `dateAdded`
- **CISA published due date** · `publishedDueDate`

Use the original source links and the field definitions below when interpreting the results. CSV works well for flat columns; JSON preserves nested values.

### Usage and pricing

Base result rate on the FREE tier: **$2 per 1,000 vulnerability observations**. The [Pricing tab](https://apify.com/maydit/cisa-kev-watchlist-monitor/pricing) shows your plan's result rate and any Actor Start charge. Set a small result limit for the first run; the requested limit is not a guarantee of that many results.

***

### Customer workflow: A CISA watchlist triage queue with stable tickets

Reconcile an explicit CVE watchlist to CISA source records, update one triage item per CVE, and distinguish catalog corrections from first observations without treating a watchlist match as asset exposure.

**Setup:** Connect your own Apify and Google Sheets triage register or a human-approved service-desk queue through [Make](https://docs.apify.com/integrations/make) or [n8n](https://docs.apify.com/integrations/n8n). Keep credentials in your connector's credential manager.

```json
{
  "vendors": [],
  "products": [],
  "cveIds": [
    "CVE-2021-44228",
    "CVE-2023-27350"
  ],
  "includeEpss": false,
  "maxResults": 100,
  "comparePrevious": true,
  "onlyChanges": false,
  "snapshotName": "customer-kev-triage-v1",
  "maxRunSeconds": 240
}
```

Start with a **300-second Run timeout** and **$0.50 maximum run charge**, alongside the input's 240-second budget. Check current pricing and the selected scope before increasing either limit.

1. Create a Triage register keyed by `cveId`, with separate customer-owned asset_match, review_owner and review_status columns. Replace the demo CVEs with your watchlist and seed the register from the first run.
2. Require a healthy SUMMARY with no source, time, spending or history errors. Compare `matchingCatalogRecords` with saved plus unchanged records before considering the matched watchlist checked. A result cap alone is not complete coverage.
3. Reuse the exact watchlist and `snapshotName` sequentially, changing `onlyChanges` to true after bootstrap. Upsert CVEs with Sheets "Append or Update Row" in n8n or a key lookup/update branch in Make.
4. Show `changedFields` and `previous` alongside current CISA actions. A reviewer matches the CVE to the organization asset/version inventory before creating or updating a remediation ticket. Keep organization deadlines separate from the CISA published due date.

| Destination information | Actor fields |
| --- | --- |
| Stable ticket key | `cveId` |
| Published software | `vendor`, `product` |
| Catalog dates | `dateAdded`, `publishedDueDate` |
| Published action | `requiredAction`, `knownRansomwareCampaignUse` |
| Review evidence | `matchedWatchlist`, `changedFields`, `previous`, `url`, `observedAt` |

**Keep the meaning:** This is a catalog watchlist, not an asset scan. A match does not prove local exposure, and catalog absence does not prove safety. EPSS is off here; enabling it does not make EPSS-only changes trigger change-only output.

**Empty or interrupted runs:** A healthy unchanged or unmatched watchlist can save zero rows. Do not close tickets automatically. `new` means new to this saved scope; filter changes can establish a separate scope and baseline.

**Reliable delivery:** Read the completed run's own SUMMARY and paginated dataset. Retain its run ID; if destination delivery fails, replay that dataset and deduplicate by run ID plus row key. Keep destination writes sequential, and write source text literally.

**Validation:** Inputs and mappings were checked locally against this Actor. The exact customer connection has not been run end to end. Choose recurrence after a manual bootstrap; this guide creates no schedule. See the [run API](https://docs.apify.com/api/v2/actors-runs-post), [pagination guide](https://docs.apify.com/api/v2/dataset-items-get), and the full Actor guide below for detailed setup and limits.

### Full guide

Turn the official CISA Known Exploited Vulnerabilities catalog into a repeatable vendor, product or CVE watchlist. Each paid row is a saved vulnerability observation with the publisher's actions, literal match evidence and optional comparison with previously saved catalog fields. Optional FIRST EPSS enrichment adds the source's current score, percentile and score date.

#### Quick start

Run with `{}` to save the latest 20 catalog additions, sorted by CISA dateAdded descending then CVE ID. No API key, login, proxy or browser is required. Empty vendor/product/CVE arrays have the same broad fallback. Console defaults and bare API input use the same behavior. The default does not enable change-only history or EPSS.

#### Useful recurring workflows

- Maintain a vendor/product watchlist for a service desk or security research workflow, retaining the exact CISA text and which terms matched.
- Observe corrections to required actions, due dates, ransomware-use flags and other published catalog fields.
- Recheck a fixed CVE list and export a stable row identity for downstream ticket reconciliation.

Terms within each vendor or product list are OR matches; populated vendor, product, exact CVE and date filters combine with AND. Vendor/product matches are literal case-insensitive substrings. They are watchlist matches, not assertions about installed versions, affected assets, exploitability in your environment or successful remediation. The Actor does not scan systems or fetch exploit code, third-party advisories or linked vendor pages.

#### Exact examples

##### Microsoft Exchange KEV watchlist

Up to five catalog observations matching Microsoft and Exchange, with literal source evidence and published actions.

Use the [copyable first-run input](#try-this-actor) above.

##### Fortinet KEV observations with EPSS

Up to five CISA Fortinet observations with optional source-dated FIRST EPSS scores and honest missing-score status.

```json
{
  "vendors": [
    "Fortinet"
  ],
  "includeEpss": true,
  "maxResults": 5
}
```

##### Named CVE watchlist with source scores

Look up Log4Shell and PaperCut CVE catalog entries, including published actions and optional FIRST EPSS metadata.

```json
{
  "cveIds": [
    "CVE-2021-44228",
    "CVE-2023-27350"
  ],
  "includeEpss": true,
  "maxResults": 2
}
```

#### Output and meaning

One row per unique `cveId` per run. Fields include `title`, `vendor`, `product`, `dateAdded`, `publishedDueDate`, `description`, `requiredAction`, `knownRansomwareCampaignUse`, nullable `forensicTriage`, `cwes`, original `notes`, `matchedWatchlist`, `contentHash`, catalog version/release time, source URLs and observation time.

The published due date is CISA's catalog field and retains its source context. It is not a deadline calculated for your organization or a legal-compliance determination. `dateAdded` means inclusion in KEV, not CVE discovery/publication. `Unknown` ransomware use remains Unknown. CISA catalog absence is not proof of safety. The catalog is a selected list, not a complete vulnerability database.

When requested, `epss` contains FIRST's 0–1 score, 0–1 percentile, date and source attribution. `epssStatus` distinguishes `available`, `not_published`, `unavailable` and `not_requested`. Missing scores stay null. EPSS estimates observed exploitation activity over the following 30 days; it is not a certainty, impact/severity score, asset-specific prediction or replacement for CISA's known-exploitation evidence. No new score or risk ranking is invented. Optional EPSS requests use batches of at most 50 CVEs, one 5-second HTTP attempt per batch, and reserve time for primary output. Low budget or endpoint failure produces partial enrichment and a clear SUMMARY.

#### Saved comparisons

Set `comparePrevious:true` to compare catalog fields. `onlyChanges:true` implies comparison and skips unchanged observations. The first run warns and emits matching observations as `comparisonStatus:new`; this means new to the saved scope, not a newly published vulnerability. A repeat with no change saves no rows and warns successfully. Ordinary repeated runs can save and charge for the same CVE observation again.

History lives in the named store `maydit-cisa-kev-watchlist-history`, separated by `snapshotName` and canonicalized watchlist/date filters. Result limits and EPSS options do not create a new catalog scope. Only confirmed saved rows update history; rejected writes do not. Previous records outside a bounded run are preserved, with no deletion inference. OnlyChanges can inspect more records than maxResults to find changed observations. At most 20,000 saved identities fit one scope. Use one writer per scope; a detected concurrent change preserves the other writer's state and reports partial status. Corrupt history fails explicitly; use a new namespace to start again.

Comparison fields are the published title, vendor, product, dates, description, required action, ransomware-use flag, forensic-triage flag, notes and sorted CWE list. Catalog-wide version/release time, observation time, source ordering and daily EPSS changes are excluded from the change hash. Thus a new unrelated catalog item does not make every existing item appear changed. `changedFields`, `previousObservedAt` and `previous` show the actual prior catalog snapshot. EPSS-only changes are intentionally not emitted in onlyChanges mode.

#### Coverage, failures and limits

The complete available catalog is fetched once, validated and filtered locally; output is bounded by maxResults, spending and run deadlines. A requested result cap is a successful bounded window. SUMMARY reports catalog size/metadata, matched/filtered records, rows saved, skipped unchanged observations, enrichment coverage and failures. It does not contain paid diagnostic rows. A source outage or malformed catalog fails. Valid empty filters and unchanged repeats warn. Partial records/enrichment, a spent budget or spending cap are explicit. Source-controlled refresh times and upstream availability are not guaranteed.

The default wall-clock budget is 240 seconds, additionally limited by the platform timeout minus 25 seconds. Requests, retries, DNS resolution, redirects and response decompression are bounded. Catalog requests honor robots guidance. Network targets and redirects must resolve to public addresses. Spending-limit preflight and confirmed-row accounting preserve rejected-row history correctly.

#### Pricing

Initial FREE/BRONZE price: **$0.002 per saved vulnerability observation**, plus **$0.00005 per Actor start**. SILVER is 20% lower per result; GOLD/PLATINUM/DIAMOND are 40% lower. Source data is public; the paid service provides watchlist processing, saved observations, comparison state and managed execution.

#### Sources and attribution

- [CISA KEV catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) and [canonical JSON](https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json), licensed [CC0 1.0](https://www.cisa.gov/sites/default/files/licenses/kev/license.txt). Third-party links have their own policies; this Actor does not fetch them. No CISA logo or government endorsement is claimed.
- [FIRST EPSS](https://www.first.org/epss/) and [public API reference](https://api.first.org/epss/). [FIRST's FAQ](https://www.first.org/epss/faq) makes scores freely accessible without registration and requests attribution. Data and timestamps are attributed to FIRST; no affiliation is claimed.

This is a catalog observation and data-export tool, with no guarantee of exhaustive vulnerability coverage, asset exposure determination.

### Help with your run

Open the **Issues** tab on this Actor with the run URL, the input field that caused trouble and what you expected to receive. Remove API keys and private information before posting.

[Explore more Mayd-It Actors](https://apify.com/maydit)

### Understand your run

Open **Run report** in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use **CSV export** to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.

The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.

# Actor input Schema

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

Up to 50 case-insensitive literal substrings of CISA vendorProject, OR within this list. Combine populated vendor/product/CVE/date filters with AND. Empty matches all vendors; terms do not establish installed software exposure.

## `products` (type: `array`):

Up to 50 case-insensitive literal substrings of CISA product. Empty matches all products. Source product names can be broad, such as Multiple Products.

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

Up to 100 exact CVE identifiers. Empty matches all CVEs. A missing CVE is not evidence that software is safe.

## `dateAddedFrom` (type: `string`):

Optional inclusive CISA dateAdded in real YYYY-MM-DD format. This is catalog addition, not vulnerability publication or discovery.

## `dateAddedTo` (type: `string`):

Optional inclusive CISA dateAdded in real YYYY-MM-DD format.

## `includeEpss` (type: `boolean`):

Optional source-labeled daily EPSS score and percentile. Uses bounded public API batches. An outage leaves honest nulls and a partial SUMMARY while preserving primary CISA output. EPSS is excluded from catalog change history.

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

Save up to this many matching observations, sorted by dateAdded descending then CVE ID. In onlyChanges mode, unchanged rows do not consume this cap. A requested cap is an intentional window, not an error.

## `comparePrevious` (type: `boolean`):

Use a named store scoped to this watchlist and snapshot name. First observations are emitted and establish history only after confirmed dataset saves. One concurrent writer per scope.

## `onlyChanges` (type: `boolean`):

Implies comparison. The first run emits matching observations with status new, meaning new to saved history. Later unchanged observations are skipped; a no-op warns and succeeds. Daily EPSS changes alone do not count.

## `snapshotName` (type: `string`):

1–80 letters, digits, underscores or hyphens. Use a new name to reset history. Different filters create different scopes. Only confirmed saved rows advance history.

## `maxRunSeconds` (type: `integer`):

Own wall-clock budget, also capped by the platform deadline minus 25 seconds. Source requests, retries, output and history obey the budget.

## Actor input object example

```json
{
  "vendors": [],
  "products": [],
  "cveIds": [],
  "includeEpss": false,
  "maxResults": 20,
  "comparePrevious": false,
  "onlyChanges": false,
  "snapshotName": "default",
  "maxRunSeconds": 240
}
```

# Actor output Schema

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

No description

## `runReport` (type: `string`):

Readable summary of saved records, reported source coverage, limits and next steps. Available when this run saves its SUMMARY.

## `csvExport` (type: `string`):

Download saved dataset records as a CSV file for spreadsheets and other tools.

## `summary` (type: `string`):

No description

# 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 = {
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("maydit/cisa-kev-watchlist-monitor").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 = { "maxResults": 20 }

# Run the Actor and wait for it to finish
run = client.actor("maydit/cisa-kev-watchlist-monitor").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 '{
  "maxResults": 20
}' |
apify call maydit/cisa-kev-watchlist-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maydit/cisa-kev-watchlist-monitor"
        }
    }
}
```

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/maBtzREXN4v3DFSGW/builds/NsITW6AXl9ZRgVAX1/openapi.json
