dpkg-cve-scanner — Smart CVE Prioritization for Debian/Ubuntu Systems
A post-exploitation enumeration tool that lists installed Debian packages, cross-references them against OSV, and enriches the results with EPSS, CISA KEV, Debian Security Tracker urgency, and public PoC detection. Prioritizes manually installed packages — the ones that actually matter during a pentest.
The problem
After getting a shell on a Linux target, the next question is always the same: what is actually vulnerable here? Running dpkg -l gives you a list of hundreds of packages. Most of them are system dependencies that shipped with the OS and have never been touched. A handful were installed manually by a developer, an administrator, or a container build process — and those are the ones that tend to have the vulnerabilities that matter.
The manual approach — checking each package against a CVE database by hand — is slow and error-prone. Worse, most public CVE databases return every CVE ever associated with a package, including ones that were patched years ago. The signal-to-noise ratio is terrible.
dpkg-cve-scanner was built to solve exactly this problem: take a list of installed Debian packages, find the CVEs associated with them, and prioritize the findings in a way that reflects what an attacker would actually care about.
What it does
The tool does four things:
- Enumerates installed packages using
dpkg-query(or reads them from a file). - Looks up CVEs for each package via the public OSV API.
- Enriches each CVE with real-world exploitability data from four sources:
- EPSS (FIRST API): probability of exploitation in the next 30 days.
- CISA KEV: whether the CVE is actively exploited in the wild.
- Debian Security Tracker: the official urgency rating (
high,medium,low,unimportant). - PoC-in-GitHub: whether public proof-of-concept code exists for the CVE.
- Prioritizes and filters the results so that the most relevant findings appear first.
The prioritization order is:
- CVEs in the CISA KEV catalog (active exploitation).
- CVEs with public PoCs.
- CVE year (newest first).
- Packages installed manually (not as dependencies).
- Packages with
optionalorextrapriority. - Debian urgency (
high→medium→low). - EPSS score.
The logic behind this order is simple: a CVE that is actively exploited, has public exploit code, and affects a package that the user installed manually is far more interesting than a CVE from 2018 affecting a system library that ships with every Debian install.
Usage
Basic scan of the local system
python3 cve_scan.py
Enumerates all installed packages, queries OSV, and prints the top 40 most prioritized vulnerabilities in a terminal table. It also writes a full JSON report to cve_report.json.
Scan a remote host via SSH
ssh user@target "dpkg-query -W -f='\${Package}=\${Version}\n'" > pkgs.txt
python3 cve_scan.py -i pkgs.txt
The tool never runs on the target — you extract the package list, transfer it to your machine, and analyze it locally. This is useful when the target is a production system you do not want to install tools on.
Scan a Docker container
docker exec <container> dpkg-query -W -f='${Package}=${Version}\n' > pkgs.txt
python3 cve_scan.py -i pkgs.txt
Scan a chroot or mounted filesystem
dpkg-query --admindir=/mnt/target/var/lib/dpkg -W -f='${Package}=${Version}\n' > pkgs.txt
python3 cve_scan.py -i pkgs.txt
Show only critical items
python3 cve_scan.py --only-kev # only actively exploited CVEs
python3 cve_scan.py --min-epss 0.5 # only EPSS >= 0.5
python3 cve_scan.py --min-year 2024 # only CVEs from 2024+
Combined filters
python3 cve_scan.py --min-year 2023 --min-epss 0.1 --top 20
Output format
The terminal output is a table with the following columns:
| Column | Meaning |
|---|---|
PACKAGE | Package name |
VERSION | Installed version |
YEAR | Year of the CVE |
CVE | CVE identifier |
EPSS | Exploit Prediction Scoring System (0-1) |
URG | Debian urgency: high, medium, low, unimportant |
ORIGIN | manual if installed by the user, auto if dependency |
POC | ★N if N public PoCs exist on GitHub |
KEV | ★ if listed in CISA’s Known Exploited Vulnerabilities catalog |
Example output:
PACKAGE VERSION YEAR CVE EPSS URG ORIGIN POC KEV
=======================================================================================
nginx 1.30.4-5 2023 CVE-2023-44487 1.000 high manual (opt) ★5 ★
cups 2.4.18-1 2026 CVE-2026-34990 0.234 high manual (opt) ★1
firefox-esr 140.15.0esr-1 2023 CVE-2023-5217 0.490 high manual (opt) ★3 ★
libreoffice 4:26.8.0.3-2 2018 CVE-2018-10583 0.783 unimportant manual -
The ★ markers for KEV and PoC make it immediately obvious which findings warrant attention. The manual tag on the ORIGIN column tells you which packages the user actually installed — those are the ones most likely to be exploitable in a pentest.
Why this matters in a pentest
The post-exploitation enumeration phase is where most pentesters waste time. Running linpeas or LinEnum gives you a wall of output, and the vulnerability findings are usually buried in the middle of it. The signal-to-noise ratio is low because those tools were designed to be comprehensive, not to prioritize.
dpkg-cve-scanner takes a different approach: it assumes that not every CVE matters, and it tries to surface the ones that do. The combination of CISA KEV (active exploitation), EPSS (probability of exploitation), and manual-package detection (user-installed software) creates a shortlist that a pentester can act on immediately.
The tool is not a replacement for linpeas or manual enumeration. It is a complement — a way to answer the question “which of these 300 packages should I actually look at?” in a few seconds instead of a few minutes.
Limitations
- OSV does not always provide a numeric CVSS score for Debian packages. The tool uses the Debian Security Tracker urgency as a proxy for severity. This is a reasonable approximation but not a perfect one.
- Old CVEs (pre-2015) are often already patched in modern versions, but Debian keeps the CVE ID for historical reasons. The
--min-epssand--only-kevfilters help reduce this noise. - Manual package detection relies on
apt-mark showmanual, which can be unreliable if the user has altered the marks manually. It is a heuristic, not a guarantee. - PoC detection relies on PoC-in-GitHub, which indexes public repositories. A CVE might have a private PoC that is not indexed there.
- When using
--inputfrom a remote host,apt-mark showmanualstill runs on the local machine. For remote manual-package detection, you need to extract the list of manual packages from the target and correlate manually (a future feature is planned).
Defense and detection
From a defender’s perspective, this tool highlights an important truth: the packages that matter are the ones that were installed manually. System packages that ship with the OS are patched by the distribution. Packages that a developer installed by hand — a custom web server, a specific version of a library, a tool downloaded from a GitHub release — are the ones that fall through the cracks.
The defensive response:
- Maintain an inventory of manually installed packages. If you know what you installed, you know what to patch.
- Prioritize patching by CISA KEV and EPSS, not by CVSS alone. A CVE with a high CVSS score but no public exploit is less urgent than a CVE with a medium CVSS score that is actively exploited.
- Monitor for enumeration activity. Running
dpkg-queryon a production system is not normal user behavior. Audit logs that record process execution will show it. - Restrict SSH access to production systems. The remote-scanning capability of this tool relies on the ability to extract package lists from a target. If SSH access is restricted, that capability is reduced.
Roadmap
The tool is actively maintained. Planned features include:
--manual-input FILEto pass the manual package list of a remote host.--csvoutput for spreadsheet-friendly reports.searchsploitintegration for local exploit lookup.- Support for RPM-based distros (RHEL, Fedora, CentOS).
- Cross-reference with exposed services (
ss -tulpn).
Takeaway
dpkg-cve-scanner is a small tool that solves a specific problem: when you have a shell on a Debian or Ubuntu system and you want to know what is actually vulnerable, the answer is not “run a scanner and read 200 pages of output.” It is “look at the packages that were installed manually, check them against the active-exploitation and high-probability-of-exploitation lists, and start there.”
The tool automates that workflow. It does not replace human judgment — it informs it. And in a pentest, informed judgment is the difference between finding the one exploitable package and spending two hours on the wrong target.