DEV Community

Jacob Cuthbertson
Jacob Cuthbertson

Posted on

I wanted to make prioritizing vulnerabilities cheaper and easier.

Security teams deal with thousands of CVEs every year. Not all of them are equally urgent, but most scoring systems give you CVSS alone, which tells you severity but not likelihood of exploitation. All of this data is open source, but it takes a few weeks of data engineering to piece together or thousands of dollars to companies like Flashpoint. I was tired of seeing the average security team get screwed so I created RiskScore.

RiskScore combines three signals into one 0–100 composite score without the massive cost:

CVSS — base severity from NVD
EPSS — exploitation probability from FIRST
CISA KEV — confirmed active exploitation status
The result: a single number you can sort, threshold, and act on. The Python SDK makes it a one-liner.

Install
pip install riskscore-api
Requires Python 3.8+. No additional system dependencies.

Get a free API key
Sign up at riskscore.dev — takes 30 seconds. Free tier is 100 requests/day, no credit card required. If you need more but can't pay, leave a comment... I will increase the request count.

You can register directly via the SDK:

from riskscore import RiskScoreClient

Registers a new account and returns your API key

client = RiskScoreClient(api_key="")
result = client.register(email="you@example.com", name="Your Name")
print(result["api_key"]) # rsk_live_...
First call: CVE-2021-44228 (Log4Shell)
from riskscore import RiskScoreClient

client = RiskScoreClient(api_key="YOUR_API_KEY")

result = client.get_cve("CVE-2021-44228")
print(result["cve_id"], result["risk_score"]["score"], result["risk_score"]["severity_label"])

CVE-2021-44228 100 CRITICAL

Log4Shell maxes out the scale: CVSS 10.0, confirmed in CISA KEV, 97th+ percentile EPSS. If you're not already patched on this one, that's your triage queue right there.

Bulk scoring: multiple CVEs in one call
Don't loop and make individual requests. Use bulk_score() to score up to 10 CVEs at once (free tier) or up to 100 (Pro):

from riskscore import RiskScoreClient

client = RiskScoreClient(api_key="YOUR_API_KEY")

cve_ids = [
"CVE-2021-44228", # Log4Shell
"CVE-2022-26134", # Confluence RCE
"CVE-2023-44487", # HTTP/2 Rapid Reset
"CVE-2024-3400", # PAN-OS command injection
"CVE-2021-45046", # Log4Shell variant
]

results = client.bulk_score(cve_ids)
for item in results:
score = item["risk_score"]["score"]
label = item["risk_score"]["severity_label"]
print(f"{item['cve_id']:20s} {score:3d} {label}")
Output:

CVE-2021-44228 100 CRITICAL
CVE-2022-26134 100 CRITICAL
CVE-2023-44487 100 CRITICAL
CVE-2024-3400 100 CRITICAL
CVE-2021-45046 95 CRITICAL
Score breakdown: understand why a CVE scored high
Every CVE response includes a score_breakdown object and a plain_english explanation you can drop directly into a ticket or report:

from riskscore import RiskScoreClient

client = RiskScoreClient(api_key="YOUR_API_KEY")

cve = client.get_cve("CVE-2021-44228")

Numeric breakdown

bd = cve["score_breakdown"]
print(f"CVSS contribution: {bd['cvss_contribution']} pts")
print(f"Exploit contribution: {bd['exploit_contribution']} pts")
print(f"EPSS contribution: {bd['epss_contribution']} pts")
print(f"Total: {bd['total']}")

Plain-English explanation

print(cve["plain_english"])
Output:

CVSS contribution: 30 pts
Exploit contribution: 30 pts
EPSS contribution: 19 pts
Total: 100

This CVE scores 100/100 because it has a critical CVSS of 10.0 (+30pts), is actively
exploited in the wild (KEV +30pts with known ransomware use), has a 100th percentile
exploitation probability (EPSS raw +19pts, percentile bonus +25pts).
This is especially useful when you need to justify patch prioritization to stakeholders who aren't fluent in CVSS vectors.

Error handling
from riskscore import RiskScoreClient, RiskScoreError

client = RiskScoreClient(api_key="YOUR_API_KEY")

try:
cve = client.get_cve("CVE-INVALID-9999")
except RiskScoreError as e:
print(e.status_code, e)
# 400 HTTP 400: CVE not found
All non-2xx responses raise RiskScoreError with the HTTP status code attached.

What's next
API reference: api.riskscore.dev/docs — full OpenAPI spec, all endpoints
More features: watchlist tracking, KEV-filtered search, score history over time
Try it free: riskscore.dev — 100 req/day, no credit card
If you're building security automation in Python and want a single signal for CVE urgency, this is the quickest path to get there without paying thousands of dollars a year.

Top comments (0)