# Vulnerability Checker: CVE, CISA KEV & EPSS for SBOMs (`reliable_tools/vulnerability-checker`) Actor

Vulnerability checker for your software inventory or SBOM: CVEs per component with CVSS, CISA KEV exploited status and due date, EPSS score, fixed version and a priority bucket. No scanning.

- **URL**: https://apify.com/reliable_tools/vulnerability-checker.md
- **Developed by:** [Reliable Tools](https://apify.com/reliable_tools) (community)
- **Categories:** Developer tools, AI
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.70 / 1,000 component checkeds

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

## Vulnerability Checker: CVE, CISA KEV & EPSS for SBOMs

No warranty, not security advice; no known exploited CVEs found does not mean secure.

This vulnerability checker takes your software inventory or SBOM and tells you, per component, which known CVEs affect
that exact version, which of them are being exploited in the wild (CISA Known Exploited Vulnerabilities catalog), the
EPSS exploit probability, the CVSS score, the version that fixes them and a clear priority bucket.

It is a lookup, not a scanner: it never touches your hosts or networks. You give it names, versions, package URLs,
CPEs, a CycloneDX or SPDX SBOM, or CVE IDs, and it checks them against public vulnerability databases.

### What it does

- **Reads any inventory format**: product names with versions (`Progress MOVEit Transfer 2023.0.0`), package URLs
  (`pkg:npm/lodash@4.17.20`), CPE names (`cpe:2.3:a:apache:log4j:2.14.1`), CycloneDX JSON or SPDX JSON SBOMs, a
  structured component list, or plain CVE IDs.
- **Finds the CVEs for that version**: open-source packages through OSV.dev, products through the NVD, using the
  version ranges published there. Every CVE says how it was matched (`version_range`, `exact_version`,
  `all_versions_listed`).
- **Flags exploited vulnerabilities**: CISA KEV status with the date added, the remediation due date, known ransomware
  use and the required action.
- **Adds the EPSS score**: the probability of exploitation activity in the next 30 days, with its percentile.
- **Tells you what to upgrade to**: the fixed version per CVE and the lowest version that fixes all of them.
- **Sorts by priority** with fixed, documented rules (see below), so you can work the list from the top.
- **Matches messy product names**: when a name like `Log4j2` or `MS Exchange` does not match the NVD product dictionary
  exactly, an AI match score picks the right NVD product (CPE) and tells you how sure it is. For this step the vendor,
  product name and version from your input are sent to an external AI service for this fixed comparison only. Turn off
  **AI product match for free-text names** to keep it off.

### Who uses it

- **MSPs and IT teams** checking a client asset list against the CISA KEV catalog.
- **Compliance teams** preparing for NIS2, DORA, the EU Cyber Resilience Act, SOC 2 or ISO 27001, who need a dated,
  sourced vulnerability list per product.
- **Procurement and vendor risk teams** answering "does this supplier's software have exploited vulnerabilities?"
- **Developers and DevSecOps** checking an SBOM from their build before a release.
- **AI agents** doing vendor reviews or security questionnaires through the API.

### Output

One row per component (or per CVE ID you looked up).

| Field | What it means |
|---|---|
| `status` | `vulnerable`, `no_known_vulnerabilities`, `version_missing`, `found` (CVE lookups), `not_found`, `product_not_identified`, `incomplete_licence_restricted`, `needs_distro_version`, `unknown_distro_release`, `not_covered`, `invalid_input` or `source_unavailable` (see Statuses below) |
| `withheldAdvisoryCount` | Package URLs only: OSV.dev records left out because their licence does not allow commercial reuse |
| `priority` | `act_now`, `high`, `medium`, `low` or `none` |
| `priorityReason` | Why the top vulnerability got that priority |
| `component`, `vendor`, `version` | What was checked |
| `cveCount` | Known vulnerabilities affecting this version |
| `exploitedCount`, `exploitedCves` | How many and which are in the CISA KEV catalog |
| `earliestKevDueDate` | Earliest CISA remediation due date |
| `ransomwareCount` | KEV entries with known ransomware use |
| `maxCvss`, `maxEpss` | Highest CVSS base score and EPSS probability |
| `upgradeTo` | Lowest version that fixes every vulnerability with a known fix |
| `noFixCount` | Vulnerabilities without a published fixed version |
| `vulnerabilities` | Per CVE: CVSS score, severity and vector, CWE, KEV fields, EPSS and percentile, fixed version, affected range, match basis, vendor advisory and patch links, NVD and OSV links, source, licence, licence URL (`licenceUrl`) and `textNote` (texts are truncated; for some sources only the ID and link are given) |
| `affectedProducts` | For CVE lookups: affected products with version ranges and fixed versions |
| `productMatch` | How the product was identified: package URL, CPE, exact name or AI match with a probability and the alternatives |
| `purl`, `cpe`, `ecosystem` | The identifiers used for the lookup |
| `summary` | One sentence for your report |
| `sources` | Sources and licences for this row, with the NVD and CISA notices |
| `disclaimer` | No warranty, not security advice; no known exploited CVEs found does not mean secure |

#### Statuses

| Status | Meaning | Charged |
|---|---|---|
| `vulnerable` | Known vulnerabilities affect this version | Yes |
| `no_known_vulnerabilities` | The sources checked list none for this version | Yes |
| `version_missing` | No version given; only exploited (KEV) vulnerabilities and malicious-package records for the product are listed | Yes |
| `found` | CVE ID looked up | Yes |
| `incomplete_licence_restricted` | Every OSV.dev record for this package comes from a source whose licence does not allow commercial reuse (Chainguard / Wolfi), so the package could not be checked. `withheldAdvisoryCount` says how many records were withheld. Never reported as clean | No |
| `needs_distro_version` | An OS package URL without a usable distribution release got no records. Add `?distro=` (for example `?distro=debian-12`, `?distro=ubuntu-22.04`, `?distro=alpine-3.20`, `?distro=almalinux-9` or `?distro=rocky-9`) and run it again. Never reported as clean | No |
| `unknown_distro_release` | The release in `?distro=` (for example `alpine-3.99`) is not known to OSV.dev, so the package could not be checked. Never reported as clean | No |
| `not_covered` | An OS package from a distribution without release-specific lookup here (for example Red Hat, CentOS, Fedora or SUSE `rpm` packages) got no records from its package URL. Never reported as clean | No |
| `not_found`, `product_not_identified`, `invalid_input`, `source_unavailable` | Unknown CVE ID or product, unreadable entry, or a source did not answer | No |

If some OSV.dev records for a package are withheld for licence reasons but others remain, the row lists the remaining
ones, sets `withheldAdvisoryCount` and says in `note` that the list may be incomplete.

Distribution releases: `?distro=` is used for Debian and Ubuntu (`deb`), Alpine (`apk`) and AlmaLinux and Rocky Linux
(`rpm`). Before a package with a release is reported clean, the Actor checks that OSV.dev has data for that release.
For other `rpm` distributions (Red Hat, CentOS, Fedora, SUSE) `?distro=` is not used: the package URL is looked up as
given, results may cover several releases and the row says so in `note`. A distribution advisory (for example a Debian
DSA) that covers several CVEs is listed once per CVE, each with its own CISA KEV and EPSS check.

The run summary (key-value store record `SUMMARY`) has counts per status and priority, the list of components to act on
now, the KEV catalog version and the EPSS score date.

#### Priority rules

The priority is set by code, not by AI, so you can explain it to an auditor:

| Bucket | Rule |
|---|---|
| `act_now` | Listed in the CISA KEV catalog, or reported as a malicious package |
| `high` | CVSS 9.0 or higher, or EPSS 10% or higher |
| `medium` | CVSS 7.0 or higher, or EPSS 1% or higher |
| `low` | Everything else |
| `none` | No known vulnerabilities in the sources checked |

The component gets the highest bucket of its vulnerabilities.

### How to run

1. Paste your items into **Software inventory**, one per line. Mix formats as you like.
2. Or paste an SBOM into **SBOM**, or give a link to it in **SBOM file URL**.
3. Or put CVE IDs from a scanner report or questionnaire into **CVE IDs**.
4. Start the run and open the **Components** view, or download as Excel, CSV or JSON.

Tips:

- Always give a version. Without one, you get only the exploited (KEV) vulnerabilities known for the product, which is
  still useful for a vendor review.
- Package URLs are the most precise input. Most SBOM tools write them for every package.
- Product names, CPEs and CVE IDs are looked up in the NVD, which allows 5 requests per 30 seconds without a key. We
  strongly recommend adding your own free NVD API key in **NVD API key**: it makes those lookups about 9 times faster
  and keeps your lookups within the NVD's published rate limits. Package URLs do not need it.
- Results are cached for a day, so a rerun of the same list is fast.

#### Input example

```json
{
  "inventory": [
    "Progress MOVEit Transfer 2023.0.0",
    "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
    "pkg:npm/lodash@4.17.20",
    "cpe:2.3:a:apache:http_server:2.4.49",
    "CVE-2021-44228"
  ],
  "components": [
    {"reference": "srv-12", "vendor": "Fortinet", "product": "FortiOS", "version": "7.2.3"}
  ]
}
```

### Example output

```json
{
  "input": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
  "inputType": "purl",
  "status": "vulnerable",
  "priority": "act_now",
  "priorityReason": "Listed in the CISA Known Exploited Vulnerabilities catalog, known ransomware use",
  "component": "org.apache.logging.log4j:log4j-core",
  "version": "2.14.1",
  "cveCount": 8,
  "exploitedCount": 2,
  "exploitedCves": ["CVE-2021-44228", "CVE-2021-45046"],
  "earliestKevDueDate": "2021-12-24",
  "ransomwareCount": 2,
  "maxCvss": 10.0,
  "upgradeTo": "2.25.4",
  "vulnerabilities": [
    {
      "cveId": "CVE-2021-44228",
      "otherIds": ["GHSA-jfh8-c2jp-5v3q"],
      "cvssScore": 10.0,
      "cvssSeverity": "CRITICAL",
      "cwes": ["CWE-20", "CWE-400", "CWE-502", "CWE-917"],
      "inKev": true,
      "kevDateAdded": "2021-12-10",
      "kevDueDate": "2021-12-24",
      "kevRansomwareUse": "Known",
      "epss": 0.99999,
      "epssPercentile": 1.0,
      "fixedIn": "2.15.0",
      "matchBasis": "version_range",
      "priority": "act_now",
      "nvdUrl": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228",
      "source": "GitHub Advisory Database via OSV.dev",
      "licence": "CC BY 4.0",
      "licenceUrl": "https://creativecommons.org/licenses/by/4.0/",
      "textNote": "Title truncated to 200 characters."
    }
  ],
  "summary": "org.apache.logging.log4j:log4j-core 2.14.1: 8 known vulnerabilities, 2 exploited in the wild (CISA KEV, earliest due 2021-12-24, known ransomware use), highest CVSS 10.0. Upgrading to 2.25.4 or later fixes all of them. Priority: act now."
}
```

### API use

Run it from your own code or an AI agent with the Apify API. Example with curl:

```bash
curl -X POST "https://api.apify.com/v2/acts/reliable_tools~vulnerability-checker/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"inventory": ["pkg:npm/lodash@4.17.20", "Progress MOVEit Transfer 2023.0.0", "CVE-2023-34362"]}'
```

To check an SBOM from your build pipeline, send it as `"sbom": { ...your CycloneDX or SPDX JSON... }` or host the file
and send `"sbomUrl"`. Fail the build when any row has `"priority": "act_now"`.

### Pricing

Pay per result, no subscription:

| Event | Price |
|---|---|
| Component checked (including clean components) | $0.002 |
| CVE ID looked up | $0.002 |
| AI product match (only when a name needed it) | $0.002 |
| Actor start | $0.00005 per run |

Invalid entries, unknown products, unknown CVE IDs, source errors, `incomplete_licence_restricted`,
`needs_distro_version`, `unknown_distro_release` and `not_covered` rows are free. A 70-component SBOM costs about $0.14.

### Sources and licences

| Source | Used for | Licence |
|---|---|---|
| CISA Known Exploited Vulnerabilities catalog | Exploited in the wild, due date, ransomware use | CC0 1.0. Use of the catalog does not imply endorsement by CISA or DHS |
| NIST National Vulnerability Database (CVE and CPE APIs) | CVE details, CVSS, CWE, affected version ranges, references, product dictionary | Public domain |
| FIRST EPSS (scores generated by Empirical Security) | Exploit probability and percentile | Free to use, attribution to FIRST EPSS |
| OSV.dev | Open-source package vulnerabilities and fixed versions | Per source, as listed on the OSV.dev data sources page (google.github.io/osv.dev/data); each row names its source, licence and licence URL |

This product uses the NVD API but is not endorsed or certified by the NVD. This Actor is not affiliated with or
endorsed by NIST, CISA, DHS, FIRST or OSV.dev.

OSV records are handled with an allow-list of record ID prefixes whose source licence is documented and allows
commercial reuse (for example GitHub Advisory Database, PyPI, Go, OSS-Fuzz and Red Hat under CC BY 4.0, RustSec under
CC0, Bitnami and OpenSSF Malicious Packages under Apache 2.0, AlmaLinux and Curl under MIT). For these, a title
truncated to 200 characters is shown with source and licence. Records from share-alike sources (Ubuntu and Alpine,
CC BY-SA 4.0), from sources without a documented licence (such as Debian) and from any prefix not on the list are
given as ID and osv.dev link only, without copied text. Records from feeds whose licence does not allow commercial use
or changes (Chainguard / Wolfi, CC BY-NC-ND 4.0) are left out; a package whose records all come from such a feed is
returned as `incomplete_licence_restricted`, free of charge, and never as clean.

### FAQ

**If no exploited CVEs are found, is my software secure?** No. The result only covers vulnerabilities published in
the sources at the time of the run and the names and versions you gave. No warranty, not security advice.

**Does it scan my servers?** No. It only looks up the names, versions and identifiers you give it. Nothing is sent to
your hosts.

**What is the CISA KEV catalog?** The list of vulnerabilities that the US Cybersecurity and Infrastructure Security
Agency knows are exploited in the wild. US federal agencies must fix them by the due date; many companies use it as
their "fix first" list.

**What is EPSS?** The Exploit Prediction Scoring System estimates the probability that a CVE will see exploitation
activity in the next 30 days. A score of 0.1 means 10%.

**Why does a product show `all_versions_listed`?** Some NVD entries list a product without a version range. The CVE may
apply to your version, but the NVD does not say which versions are affected, so check the vendor advisory.

**Why is `upgradeTo` empty for some CVEs?** The source lists the last affected version but no fixed version yet. Those
are counted in `noFixCount`.

**How reliable is the AI product match?** Every match comes with a probability and the alternatives it considered. Names
that match the NVD dictionary exactly skip the AI. Below 0.6 the product is reported as not identified and you are not
charged; give the CPE or the vendor and product as the NVD writes them.

**Which SBOM formats work?** CycloneDX JSON (1.2 to 1.6) and SPDX JSON (2.2 and 2.3). Components with a package URL are
checked through OSV.dev, components with a CPE or only a name and version through the NVD.

**Something broke or a field is missing?** Open an issue on the Issues tab and we'll look at it.

### About Reliable Tools

This Actor is made by [Reliable Tools](https://apify.com/reliable_tools). We build tools that return clean data from
official sources plus an AI label with a confidence score where it helps, so you can filter and act on the results
straight away. Our focus is compliance, e-commerce, product sourcing and lead research.

If a field is missing or an entry doesn't match the way you expect, open an issue on the Issues tab. We read every one
and usually reply within a day. You can find our other Actors on our [profile page](https://apify.com/reliable_tools).

# Actor input Schema

## `inventory` (type: `array`):

One item per line. Each line can be a product name with version (Apache Log4j 2.14.1), a package URL (pkg:npm/lodash@4.17.20), a CPE name (cpe:2.3:a:apache:log4j:2.14.1) or a CVE ID (CVE-2023-34362). Without a version you get only the exploited vulnerabilities known for that product.

## `components` (type: `array`):

Optional: one object per component from your asset list. Fields: "reference", "vendor", "product" (or "name"), "version", "cpe", "purl". Example: {"reference": "srv-12", "vendor": "Fortinet", "product": "FortiOS", "version": "7.2.3"}.

## `sbom` (type: `object`):

Optional: paste a whole CycloneDX JSON or SPDX JSON document. Every component with a package URL, CPE or name and version is checked.

## `sbomUrl` (type: `string`):

Optional: a public link to a CycloneDX JSON or SPDX JSON file (up to 50 MB).

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

Optional: CVE IDs to look up directly, for example from a scanner report or a security questionnaire.

## `minimumPriority` (type: `string`):

Shortens the vulnerability list inside each row. Counts, priority and the upgrade version always cover all vulnerabilities found.

## `aiProductMatch` (type: `boolean`):

When a product name does not match the NVD product dictionary exactly (for example Log4j2, MS Exchange), an AI match score picks the right NVD product. Each pick comes with a probability. Off: only exact names are matched.

## `nvdApiKey` (type: `string`):

Optional free key from the NVD (nvd.nist.gov, Request an API Key). The NVD allows 5 requests per 30 seconds without a key and 50 with one, so a key makes name, CPE and CVE lookups about 9 times faster. Package URLs do not need it.

## `maxCvesPerComponent` (type: `integer`):

Caps very large products (for example an operating system kernel) so a run stays fast.

## `maxComponents` (type: `integer`):

Entries over this limit are skipped and not charged.

## Actor input object example

```json
{
  "inventory": [
    "Progress MOVEit Transfer 2023.0.0",
    "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
    "pkg:npm/lodash@4.17.20",
    "cpe:2.3:a:apache:http_server:2.4.49",
    "CVE-2021-44228"
  ],
  "minimumPriority": "low",
  "aiProductMatch": true,
  "maxCvesPerComponent": 300,
  "maxComponents": 1000
}
```

# Actor output Schema

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

Dataset in the components view.

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

Counts per status and priority, components to act on now, data versions and source credits.

# 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 = {
    "inventory": [
        "Progress MOVEit Transfer 2023.0.0",
        "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
        "pkg:npm/lodash@4.17.20",
        "cpe:2.3:a:apache:http_server:2.4.49",
        "CVE-2021-44228"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("reliable_tools/vulnerability-checker").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 = { "inventory": [
        "Progress MOVEit Transfer 2023.0.0",
        "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
        "pkg:npm/lodash@4.17.20",
        "cpe:2.3:a:apache:http_server:2.4.49",
        "CVE-2021-44228",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("reliable_tools/vulnerability-checker").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 '{
  "inventory": [
    "Progress MOVEit Transfer 2023.0.0",
    "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
    "pkg:npm/lodash@4.17.20",
    "cpe:2.3:a:apache:http_server:2.4.49",
    "CVE-2021-44228"
  ]
}' |
apify call reliable_tools/vulnerability-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,reliable_tools/vulnerability-checker"
        }
    }
}
```

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/zXyqOwKYpxv3naFHa/builds/v7V1kqKzYMBVodcXw/openapi.json
