PatchRank
Patch Tuesday, ranked by who's actually being attacked — not by how scary the label looks.
English · Русский
The 30-second version
Microsoft's July 2026 security document contained 2,070 CVEs. You have a morning to decide what to deploy first.
Everyone sorts by severity and starts with "Critical". Here is what that actually gets you, computed from the real data:
- 106 of the 117 Critical-rated CVEs (91%) have an exploit probability under 1%, appear in no CISA exploitation catalogue, and are not flagged as exploited by anyone.
- Four CVEs were confirmed exploited in the wild. Two of them were not rated Critical. One was rated Moderate, CVSS 5.3.
- So a "Critical only" filter hands you 117 mostly-irrelevant items and misses half the bugs attackers were actually using.
That Moderate-rated one — CVE-2026-56164, a SharePoint privilege escalation in the CISA KEV catalogue with a 22% 30-day exploit probability — sits at position #1090 out of 2070 if you sort by CVSS. And that is its best possible position, because 18 other CVEs share its exact score.
Nobody scrolls to #1090.
It is not a one-month fluke
Run patchrank verify on any cycle. Four consecutive months, computed from live data:
| Cycle | CVEs | "Critical" with no exploitation signal | Confirmed exploited | ...of those, not rated Critical |
|---|---|---|---|---|
| 2026-Apr | 701 | 86% | 5 | 5 of 5 |
| 2026-May | 1,128 | 79% | 4 | 3 of 4 |
| 2026-Jun | 991 | 84% | 1 | 1 of 1 |
| 2026-Jul | 2,070 | 91% | 4 | 2 of 4 |
Across those four cycles, 14 CVEs were confirmed exploited in the wild. Exactly 3 of them were rated Critical.
In April, a "Critical only" filter would have missed every single one.
$ patchrank triage --top 4
SCORE BAND CVE SEVERITY CVSS EPSS SIGNALS TITLE
91 ACT NOW CVE-2026-50522 Critical 9.8 75.76% KEV Microsoft SharePoint Remote Code Execution…
87 ACT NOW CVE-2026-58644 Critical 9.8 5.99% KEV EXPL Microsoft SharePoint Remote Code Execution…
85 ACT NOW CVE-2026-56164 Moderate 5.3 22.44% KEV EXPL Microsoft SharePoint Server Elevation of P…
79 ACT NOW CVE-2026-56155 Important 7.8 2.33% KEV EXPL Active Directory Federation Services Eleva…
Severity answers "how bad would this be if someone did it?". Triage needs "is anyone doing it?". Those are different questions, and the free public data to answer the second one already exists — scattered across three feeds that nothing joins.
PatchRank joins them.
Install
pip install patchrank
patchrank triage
No dependencies. Nothing to configure. No API key, no account, no telemetry. The first run downloads the current cycle and prints a ranked list.
Run without installing anything
git clone https://github.com/Ax1zz/patchrank && cd patchrank
PYTHONPATH=src python3 -m patchrank triage
Python 3.9+ and the standard library are the only requirements.
What it does
Joins three free, unauthenticated public sources and ranks the result:
| Source | Contributes |
|---|---|
| Microsoft MSRC CVRF | CVEs, severity, CVSS, affected products, KB numbers, Microsoft's own exploited / publicly-disclosed flags and Exploitability Index |
| FIRST.org EPSS | Probability of exploitation in the next 30 days, and percentile |
| CISA KEV | Confirmed known-exploited catalogue, federal remediation deadline, ransomware-campaign association |
Usage
patchrank triage # this month, ranked
patchrank triage 2026-Jul # a specific cycle
patchrank triage --top 10 # just the ones that matter
patchrank triage -p "Windows Server 2022" # only what you actually run
patchrank triage -p Exchange -p SharePoint
patchrank triage --kev-only # only confirmed-exploited
patchrank triage --min-epss 0.05 # only >5% exploit probability
patchrank explain CVE-2026-56164 # why did this rank here?
patchrank verify # re-run the analysis above yourself
patchrank weights # show the scoring model
patchrank products --grep Exchange # discover --product patterns
patchrank months # list available cycles
patchrank cache # inspect / --clear the local cache
Month formats are forgiving: 2026-Jul, 2026-07, Jul-2026, July 2026, 202607, or latest.
Built to be piped
patchrank triage --format json | jq '.vulnerabilities[] | select(.in_kev)'
patchrank triage --format csv > cycle.csv
patchrank triage --format markdown --top 10 > change-ticket.md
Exit codes: 0 success · 1 runtime error · 2 bad usage · 3 nothing matched. So this works:
if patchrank triage --kev-only --format json > kev.json; then
slack-notify "Confirmed-exploited CVEs this cycle" < kev.json
fi
Justify the decision
Nobody gets to reorder a patch cycle without explaining why. Every score is fully attributable:
Check the premise yourself
The claim this tool rests on is falsifiable, so it ships with the test. patchrank verify recomputes it against live data for any month. If Microsoft's severity ratings ever start tracking real exploitation, this command will say so and PatchRank will have argued itself out of a job.
The scoring model
Deterministic, documented, and weighted so that evidence of exploitation always beats theoretical severity. No model calls, no heuristics you can't inspect.
| Signal | Points | Why |
|---|---|---|
| Listed in CISA KEV | +40 | Confirmed exploited. The strongest signal that exists. |
| KEV ransomware campaign use | +15 | Escalates from theoretical to operational. |
Microsoft flags Exploited:Yes |
+25 | Vendor confirms exploitation detected. |
| EPSS probability | +0…30 | sqrt(EPSS) × 30 — square root so a 4% probability still registers instead of rounding to nothing. |
| Exploitability Index "More Likely" | +10 | Microsoft's own forward-looking forecast. |
| Publicly disclosed pre-patch | +8 | Exploit details already in the open. |
| CVSS base score | +0…12 | CVSS × 1.2. Deliberately the smallest lever — severity is the least predictive input. |
| Impact is Remote Code Execution | +3 | Mild adjustment for attack-chain value. |
One non-additive rule, and it earns its place: a CVE with confirmed exploitation is never ranked below URGENT (50), whatever its severity. That is exactly the CVE-2026-56164 case — Moderate, CVSS 5.3, actively used against SharePoint servers. Pure addition would have filed it under "schedule it later".
Two invariants, both enforced by tests:
- Confirmed exploitation always lands in
URGENTor above. - Severity alone can never reach
ACT NOW. A perfect CVSS 10.0 RCE with no exploitation evidence maxes out at 25 points.
| Band | Score | Meaning |
|---|---|---|
ACT NOW |
≥ 70 | Exploited or near-certain. Emergency change. |
URGENT |
50–69 | Strong exploitation signal. This cycle, prioritised. |
SCHEDULED |
25–49 | Normal cycle. |
ROUTINE |
< 25 | Batch it. |
How it compares
| PatchRank | MsrcSecurityUpdates | PatchaPalooza | patch-tuesday | Vendor blogs | |
|---|---|---|---|---|---|
| MSRC data | ✅ | ✅ | ✅ | ✅ | ✅ |
| + EPSS probability | ✅ | ❌ | ❌ | ❌ | sometimes |
| + CISA KEV join | ✅ | ❌ | ❌ | ❌ | sometimes |
| Ranked, not just listed | ✅ | ❌ | partial | partial | prose |
| Per-CVE explainability | ✅ | ❌ | ❌ | ❌ | prose |
| Cross-platform | ✅ | PowerShell only | ✅ | ✅ | n/a |
| JSON / CSV / Markdown out | ✅ | HTML report | ❌ | partial | ❌ |
| Installable from a package index | ✅ | ✅ | ❌ | ❌ | n/a |
| Runtime dependencies | none | PowerShell + auth setup | several | several | n/a |
| Offline / air-gapped mode | ✅ | ❌ | partial | ❌ | ❌ |
Verified against the GitHub and PowerShell Gallery APIs on 2026-08-03. PatchaPalooza: 222 stars, last release Feb 2026. patch-tuesday: 28 stars, active. Immersive-Labs-Sec/msrc-api: 119 stars, last push Jan 2024.
The honest summary: several tools read the MSRC feed. None of them join it to EPSS and CISA KEV, which is the join that changes the answer.
Why this exists
This keeps getting built and then abandoned. Immersive-Labs-Sec/msrc-api last moved in January 2024. Individual practitioners write a script for themselves each Patch Tuesday and stop maintaining it, because free public data supports no SaaS margin — too small for a company, right-sized for a maintained open-source tool.
Meanwhile the problem is getting worse, not better. From a practitioner writing about triage workflow:
"Microsoft drops 150-plus CVEs on a Tuesday morning. By Wednesday afternoon, the security team wants a deployment plan, the change board wants a ring schedule, and someone in Slack is asking whether 'that CLFS thing' is the one they should care about. You have half an hour before the next meeting."
And on the specific failure mode PatchRank exists to fix:
"This is the phase most triage workflows skip, and it is where the actual exploited bugs tend to hide… None of those [exploited EoP zero-days] would have surfaced on a Critical-only filter. None would have made it on a CVSS-9-or-higher cut."
Even the vendor's own forward-looking rating is under strain:
"What this means is that our way of looking at Patch Tuesday has changed, because the exploitability index is centered around humans, not AI tools, and as these tools continue to improve, defense needs to improve alongside it."
— Satnam Narang, Tenable, quoted in Krebs on Security
Related discussion threads that informed the design: r/sysadmin on patch approval workflow, r/patchmanagement. (Linked as context — Reddit blocks automated access, so nothing from these threads is quoted here.)
Design decisions
Zero dependencies, on purpose. The target user is deciding whether to install something on a privileged workstation. A tool with no supply chain is easier to get approved. Even the coloured table renderer is hand-written rather than pulling in rich.
It never touches a machine. PatchRank is decision support. It has no deployment capability, needs no privileges, and makes no network calls beyond the three documented read-only feeds. That boundary is deliberate and permanent.
Cached and air-gap friendly. Everything is cached under $XDG_CACHE_HOME/patchrank. Warm the cache on a connected machine, copy the directory to an isolated change-management workstation, and run with --offline.
Degrades loudly, not silently. If EPSS or KEV is unreachable, you still get a ranked list, with a warning telling you which signal is missing. A worse ranking beats no ranking at Patch Tuesday 09:00.
Not in scope
Deploying patches. Non-Microsoft vendors. A web UI. Inventory awareness (--product filtering is manual by design). Historical trend analytics. Writing to your ticketing system — emit Markdown or JSON and pipe it.
Roadmap
-
--diffagainst the previous cycle: what's new, what changed severity - Optional NVD enrichment for CVEs missing a CVSS vector
-
--format sariffor security-tooling pipelines - Configurable weights via
~/.config/patchrank/weights.tomlfor teams with a different risk appetite - Adobe and Chrome advisory feeds behind a
--vendorflag
Contributing
See CONTRIBUTING.md. Two hard rules: the tool keeps zero runtime dependencies, and any change to the scoring model must come with tests proving the two invariants above still hold.
git clone https://github.com/Ax1zz/patchrank && cd patchrank
pip install -e ".[dev]"
python -m pytest
Data sources and licensing
PatchRank reads only public data. MSRC CVRF is published by Microsoft; EPSS is published by FIRST.org under their terms; the KEV catalogue is published by CISA as a US Government work. PatchRank is not affiliated with Microsoft, FIRST.org, or CISA.
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file patchrank-1.0.0.tar.gz.
File metadata
- Download URL: patchrank-1.0.0.tar.gz
- Upload date:
- Size: 53.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15c1c4234bec3fe6d40b29b075f894f588634fcc5a584533a08329d613781722
|
|
| MD5 |
b3ca6a208fc8487a1cb27542b2500c13
|
|
| BLAKE2b-256 |
0dc902eb70fe92342980f3f7e7a66db7452352ad0fc64bc7549c3e08ed83d06e
|
File details
Details for the file patchrank-1.0.0-py3-none-any.whl.
File metadata
- Download URL: patchrank-1.0.0-py3-none-any.whl
- Upload date:
- Size: 42.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cefa66b40d1b011adc4cf5f3a03ed7f6486cd5e44ad64a0dba02d7febfd8dfa0
|
|
| MD5 |
73a3d66e951cda9569886068b86df1f1
|
|
| BLAKE2b-256 |
89f9bd6d19845e8a1c2143a21f5c58907dc1a5a32c908b5252b826e15c0dd8af
|