Skip to main content

icsprio

DOI

Status: v1.0.0 (verified — see Verification) | Maintainer: Friday Ogochukwu Ikwuogu, ORCID 0009-0009-2222-1318 | License: code MIT, joined data CC BY 4.0

icsprio is an open Python package that fetches, joins, and prioritizes ICS (industrial control systems) vulnerability intelligence from five public sources — CISA ICS Advisories, the CISA Known Exploited Vulnerabilities (KEV) catalog, FIRST.org's EPSS, CISA's Vulnrichment SSVC/CVSS enrichment, and MITRE ATT&CK for ICS — into one deterministic, reproducible table with an OT-relevant priority score. It is built for operators, researchers, and auditors who need a defensible, explainable answer to "which of these ICS advisories should we act on first," instead of five browser tabs and a spreadsheet.

Every number icsprio produces is reproducible: given the same fetched data and the same scoring weights, two runs never disagree, and every weight and mapping decision is documented and author-reviewed, not a black box.

What is here

icsprio/                    the installable package (fetchers, join, scoring, QA, CLI)
icsprio/reference_data/     cwe_to_attack_ics.csv — the author-reviewed CWE->ATT&CK crosswalk
code/                       numbered scripts in run order (thin wrappers over icsprio/)
data/raw/                   inputs as fetched, with PROVENANCE.txt (created by `fetch`)
data/processed/             joined table, qa_report.txt, stats.json (created by `build`)
docs/                       CODEBOOK, SCORING, ATTACK_MAPPING, LIMITATIONS, VERIFY_CHECKLIST, NEXT_STEPS
tests/                      offline pytest suite (fixtures only, no network calls)
paper/                      JOSS-format paper draft (prepared, not yet submitted)

Install

pip install icsprio            # once published to PyPI
# or, from a clone:
pip install -e ".[dev,parquet]"

Requires Python 3.9+. Runtime dependencies are deliberately minimal: requests, pandas, click, PyYAML.

Run it

icsprio run                 # fetch + join + score + QA in one call
icsprio report               # print the QA report

or, to re-score already-fetched data (e.g. after editing docs/SCORING.md's weights) without hitting the network again:

icsprio fetch --since-year 2023
icsprio build --weights-file my_weights.yaml

or the numbered scripts, if you'd rather not install the CLI:

python code/01_fetch.py --since-year 2023
python code/02_build.py
python code/03_qa.py

A stranger should be able to run any of the above from this README alone and get data/processed/icsprio_joined.csv and qa_report.txt.

Default scope

By default, fetch pulls ICS advisories from the last 3 years (--since-year <current year - 3>), not the full historical archive. This is a deliberate default, not a limitation of the data — see docs/LIMITATIONS.md for why, and pass --since-year 2010 (or any earlier year) for a full historical pull. Set the GITHUB_TOKEN environment variable to raise GitHub's API rate limit for larger pulls.

Sources

Source What it provides Vintage License / terms Accessed
CISA ICS Advisories (CSAF 2.0), via cisagov/CSAF Advisory metadata, vendor/product, CVEs ongoing U.S. Government work, public domain 2026-09-13
CISA KEV catalog Confirmed real-world exploitation updated continuously U.S. Government work, public domain 2026-09-13
FIRST.org EPSS Exploitation-likelihood score daily, back to 2021-04-14 FIRST.org terms of use 2026-09-13
CISA Vulnrichment SSVC decision points, CVSS, CWE ongoing (partial CVE coverage) CC0-1.0 2026-09-13
MITRE ATT&CK for ICS Adversary technique catalog versioned releases ATT&CK Terms of Use 2026-09-13

How prioritization works

priority_score (0-100) is a deterministic weighted combination of KEV status, EPSS percentile, and Vulnrichment's SSVC decision points. The exact weights and the rationale for each are in docs/SCORING.md — read that before trusting or citing a score; it is icsprio's own analytic contribution, not a value CISA or FIRST publishes. attack_technique_ids comes from a documented, author-reviewed CWE-to-ATT&CK-for-ICS heuristic crosswalk (no authoritative CVE-to-technique mapping exists) — see docs/ATTACK_MAPPING.md.

Headline numbers

From data/processed/stats.json, generated by a real icsprio run against live sources (2026-09-13, --since-year 2023):

  • 1,685 advisories fetched, 8,653 (advisory, CVE) rows, 7,107 unique CVEs
  • Join match rates: KEV 1.0%, EPSS 99.7%, Vulnrichment 78.9%, ATT&CK-for-ICS mapped 5.9%
  • Priority bands: Critical 83, High 37, Medium 1,978, Low 6,555
  • 0 sanity-check problems

Re-run icsprio run yourself and these numbers regenerate from your own live fetch — never take them as static.

Verification

This release has cleared the author verification gate (docs/VERIFY_CHECKLIST.md): a live icsprio run against real sources, the full pytest suite passing, and a hand review of docs/SCORING.md's weights and icsprio/reference_data/cwe_to_attack_ics.csv's crosswalk.

See docs/LIMITATIONS.md for what remains provisional by design (e.g. the crosswalk is a documented heuristic, not a MITRE mapping) rather than unfinished.

Publishing

Published on GitHub and archived on Zenodo (10.5281/zenodo.22732040); see docs/PUBLISH_GUIDE.md for PyPI steps.

Citation

See CITATION.cff. DOI: 10.5281/zenodo.22732040.

Contributing

See CONTRIBUTING.md.

Authors

See AUTHORS.json — the single source of truth for authorship across this README, CITATION.cff, the JOSS paper, and Zenodo metadata.

Metadata

Release files for icsprio 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for icsprio 1.0.0
File Size Uploaded
icsprio-1.0.0.tar.gz 46.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for icsprio 1.0.0
File Interpreter ABI Platform
icsprio-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 81.7 kB

Release files / icsprio-1.0.0.tar.gz

Download URL icsprio-1.0.0.tar.gz
Size 46.0 kB
Tags Source
SHA-256 checksum
How to use checksums
93056384a40e98130bb363bc65b5456ec17a37dbaa8547dddae6419dff72b50c
BLAKE2b-256 checksum
How to use checksums
997e1aabf05936ebcc6dc5375e6288cf1c8f99a0aed0f9445ee5910c7c207aa5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / icsprio-1.0.0-py3-none-any.whl

Download URL icsprio-1.0.0-py3-none-any.whl
Size 35.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9f31191955c709ee10ed69da8c4efdd2dbc0ef9277357106b10871f23b12aeb3
BLAKE2b-256 checksum
How to use checksums
f50049cd941ff3853c6e05e73ca5124fd485be2068d8b0a7bcff3226b464be88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page