Most vulnerability advice is useless in practice: subscribe to feeds, read announcements, patch quickly. Nobody has time to map thousands of CVEs against their own package list by hand. The useful question is narrower. Not "what vulnerabilities exist" but "which vulnerabilities affect the exact package versions installed on my servers, right now."
Key Takeaways
- Start from your actual installed package inventory. Without it you are reading advisories and guessing.
- OSV aggregates distro-specific advisories and is free to query, which makes the mapping mechanical rather than manual.
- The ecosystem string matters. The same upstream package has different answers on Ubuntu 24.04 and Debian 12.
- Backported fixes break naive version comparison, so compare against distro advisories rather than upstream release numbers.
- A one-off scan is a snapshot. The value comes from tracking findings through to resolution over time.
Table of Contents
- Start with what you actually have
- Query against a vulnerability database
- The nuance people miss
- Prioritising what to fix first
- Making it continuous
Start with what you actually have
# Debian/Ubuntu
dpkg-query -W -f='${Package} ${Version}\n'
# RHEL family
rpm -qa --qf '%{NAME} %{VERSION}-%{RELEASE}\n'
# Alpine
apk list --installed
That inventory is the foundation. Without it you are guessing.
Worth knowing what this inventory does not include: anything installed outside the package manager. Language dependencies from npm, pip, or cargo, binaries downloaded and dropped into /usr/local/bin, and anything running inside a container image are all invisible to the commands above. Those need their own inventory, and on a typical application server they are where a large share of the real exposure lives.
Query against a vulnerability database
OSV.dev aggregates vulnerability data across ecosystems, including distro-specific advisories, and exposes a free API. You can query a single package and version:
curl -s -X POST https://api.osv.dev/v1/query \
-d '{"package":{"name":"jq","ecosystem":"Ubuntu:24.04"},"version":"1.7.1-3ubuntu0.24.04.2"}'
The ecosystem string matters. Ubuntu:24.04 and Debian:12 return different results for the same upstream package, because distros backport fixes on their own schedule.
For a whole server rather than one package, batch the queries:
dpkg-query -W -f='{"package":{"name":"${Package}","ecosystem":"Ubuntu:24.04"},"version":"${Version}"}\n' \
| head -100 | jq -s '{queries: .}' \
| curl -s -X POST https://api.osv.dev/v1/querybatch -d @- | jq '.results[] | select(.vulns)'
Adjust the ecosystem string to match the server you are querying. Running this against the wrong distribution version produces confident, wrong answers.
The nuance people miss
A CVE with no vendor fix is not actionable yet. Plenty of medium-severity issues sit unpatched because the distro has not shipped a fixed version. Tracking them is useful. Panicking about them is not.
Backports break naive version comparison. Ubuntu's 1.7.1-3ubuntu0.24.04.2 may already contain the fix that upstream shipped in a later version number. Compare against distro advisories, not upstream releases.
Severity labels vary by source. A vendor's "low" and a CVSS score can disagree. Use whichever your compliance framework expects, and be consistent.
Installed is not the same as reachable. A vulnerability in a library that ships on the system but is never loaded by anything you run is a lower priority than the same score in your web server. Scanners rarely make this distinction, and it is one of the main reasons vulnerability lists feel unmanageable.
Prioritising what to fix first
A raw list sorted by CVSS score is not a work queue. What determines actual risk on a specific server is closer to this:
Is the affected service exposed? A flaw in a package listening on a public interface outranks the same score in something reachable only from localhost. Check what is actually listening:
ss -tulpn
Is there a fix available? Findings with a shipped patch are actionable now. Findings without one go on a watch list, not a to-do list.
Is it being exploited? Known exploited vulnerability catalogues change the calculus considerably, regardless of the base score.
What does the server do? The same package on a staging box with synthetic data and on a production database carry different consequences. This is judgement your team holds and no scanner can supply, one of the things that stays human in the division described in why manual server monitoring fails at 3am.
Making it continuous
A one-off scan is a snapshot. Similar to file integrity monitoring, a single check only tells you what's true right now - the value is in tracking it over time. Packages change with every update, and new CVEs are published daily against versions you already run. The scan needs to repeat and the results need to be diffable, what is new since last week, what has been fixed, what is still waiting on a vendor. It's the same constraint that decides whether alert triage scales or drowns a team: state has to persist between runs, not get rebuilt from a fresh list every time.
The practical test of whether a vulnerability process is working is not whether it produces a list. It is whether the same finding stops appearing after you fix it, and whether a genuinely new one is distinguishable from the four hundred you already knew about.
SecAI runs this loop automatically: it inventories installed packages per server, queries OSV on a schedule, and tracks each finding through to resolution rather than re-reporting the same list forever. See it alongside the rest of the detection stack. Where vulnerability tracking fits with the other controls is set out in the guide to Linux server security software.
Frequently Asked Questions
Is OSV better than the National Vulnerability Database for this? For distro packages, OSV is more directly useful because it carries distro-specific advisories that account for backports. NVD is the broader reference; OSV answers the narrower question you actually have.
How do I handle a CVE with no available fix? Track it, reduce exposure if you can, restrict access to the affected service, disable the feature if unused, and revisit when the vendor ships. Document the decision if you have a compliance obligation.
Do I need to scan containers separately? Yes. The host package inventory says nothing about what is inside an image. Container contents need their own inventory and their own scan.
How often should this run? Daily is reasonable. New advisories are published continuously against versions you already have installed, so the exposure changes without anything on your server changing.
Does patching everything immediately make sense? No. Unattended upgrades for security patches are sensible on most servers, but blanket immediate patching creates its own outage risk. Prioritise exposed and exploitable first.
Keeping that inventory current by hand does not last. Continuous monitoring of a VPS matches installed packages against published CVE data automatically.
Doing this continuously rather than on a schedule is what Linux vulnerability and CVE monitoring automates.