Feature: Risk Scoring Engine
Relevant source files
The following files were used as context for generating this wiki page:
The FixOps Risk Scoring Engine is a core component designed to prioritize vulnerability remediation by creating a composite risk score. It enriches Software Bill of Materials (SBOM) data with external threat intelligence from sources like the Exploit Prediction Scoring System (EPSS) and the CISA Known Exploited Vulnerabilities (KEV) catalog. The engine analyzes factors such as exploit probability, active exploitation, component version lag, and exposure to generate a "FixOpsRisk" score.
This scoring mechanism is central to the platform's risk-first posture, enabling teams to focus on the most critical threats. The generated risk data is consumed by various parts of the platform, including the Provenance Graph Service and the Evidence Bundler, and is accessible through both a REST API and a command-line interface (CLI) for seamless integration into CI/CD pipelines and security workflows.
Sources: readme_updated.md:47, readme_updated.md:92, readme_updated.md:356
Architecture and Data Flow
The Risk Scoring Engine operates by joining a normalized SBOM with data from threat intelligence feeds. This process is orchestrated by the core scoring logic, which can be triggered via the CLI or API. The final output is a JSON artifact containing detailed risk information for each component and CVE.
The following diagram illustrates the high-level data flow of the risk scoring process.
Threat Intelligence Feeds
The engine relies on up-to-date threat intelligence feeds, which are downloaded and cached locally.
Sources: readme_updated.md:359
EPSS Feed
The Exploit Prediction Scoring System (EPSS) feed provides data on the probability of a vulnerability being exploited.
- Source: The
epss.pymodule fetches a GZIP-compressed CSV file fromhttps://epss.cyentia.com/epss_scores-current.csv.gz. - Processing: It reads the CSV, extracts the CVE, EPSS score, and percentile, and caches the data.
- Output: The processed data is stored in
data/feeds/epss.json. - Function:
load_epssinrisk/feeds/epss.pyhandles loading the feed from the cache.
Sources: risk/feeds/epss.py, readme_updated.md:385
CISA KEV Feed
The CISA Known Exploited Vulnerabilities (KEV) catalog provides a list of vulnerabilities that are known to be actively exploited in the wild.
- Source: The
kev.pymodule fetchesknown_exploited_vulnerabilities.jsonfrom CISA's official URL. - Processing: It parses the JSON and extracts the list of KEVs.
- Output: The data is cached in
data/feeds/kev.json. - Function:
load_kevinrisk/feeds/kev.pyis responsible for loading the cached feed.
Sources: risk/feeds/kev.py, readme_updated.md:386
FixOpsRisk Scoring Engine
The core of the feature resides in risk/scoring.py, which calculates the final risk profile.
Sources: risk/scoring.py
Scoring Logic
The primary function compute_risk_profile orchestrates the scoring process. It takes a normalized SBOM and the loaded threat feeds as input. For each component in the SBOM, it performs the following steps:
- Collects Exposure Flags: Identifies potential exposure based on component names (e.g., 'nginx', 'apache').
- Infers Version Lag: Calculates the age of a component version in days if release date information is available.
- Calculates Lag Factor: Converts the version lag into a risk factor, which is capped and scaled.
- Computes FixOpsRisk: A composite score is calculated for each CVE associated with a component. The formula weights several factors:
- EPSS score (if available)
- KEV status (binary flag)
- Version lag factor
- Exposure flags
The final risk profile includes a summary and detailed breakdowns per component and per CVE.
Sources: risk/scoring.py, readme_updated.md:425
Key Data Structures
The main output is a JSON object with a well-defined structure, as validated in the system's tests.
| Field | Type | Description |
|---|---|---|
summary | object | An overview of the risk profile, including total components and CVEs. |
components | object | A dictionary mapping component PURLs to their risk details. |
cves | object | A dictionary mapping CVE IDs to their risk details and affected components. |
A component entry contains fields like fixops_risk, epss, kev_present, and version_lag_days.
Sources: tests/test_risk_scoring.py
API Interface
The risk scores and data are exposed via a REST API for UI consumption and integrations. The API is defined in backend/api/risk/router.py.
This diagram shows a typical API request to get risk details for a specific CVE.
Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/risk/cve/{cve_id} | GET | Retrieves the risk profile for a specific CVE ID. |
/api/v1/risk/component/{purl} | GET | Retrieves the risk profile for a specific component identified by its Package URL (PURL). |
Sources: backend/api/risk/router.py, readme_updated.md:424
Command-Line Interface (CLI)
For local analysis and CI/CD integration, the risk scoring engine can be invoked via the fixops-risk CLI tool.
Sources: cli/fixops_risk.py, readme_updated.md:47
Usage
The primary command is score, which generates the risk.json artifact from an SBOM.
Example Command:
fixops-risk score --sbom artifacts/sbom/normalized.json --out artifacts/risk.json
Sources: readme_updated.md:377
score Command Options
| Option | Argument | Description |
|---|---|---|
--sbom | PATH | Required. Path to the normalized SBOM JSON file. |
--out | PATH | Required. Path to write the output risk profile JSON file. |
--epss | PATH | Optional path to a custom EPSS feed file. |
--kev | PATH | Optional path to a custom KEV feed file. |
Sources: cli/fixops_risk.py