OS-package CVE matching (OSV.dev)
monsys captures the package inventory the agent already reports — apt,
dpkg, dnf, yum, rpm, apk, zypper — and queries
OSV.dev for known CVEs against the exact installed
versions. No remote scanner runs, no agent on the host changes; the
matching happens in the hub against an open public dataset.
Why this exists
The hub already runs three CVE pipelines:
- Application dependencies — OSV.dev against
package.json,requirements.txt,composer.lock,go.sum. Shipped in schema 035. - Container images — Trivy against image manifests. Shipped in schema 035.
- Kernel — Distro trackers (USN, Debian Security Tracker, RHEL CSAF, Gentoo GLSA) against the running kernel release. Shipped in schema 093.
The gap was OS packages on the host itself: an unpatched libssl3,
apache2, nginx, glibc. Schema 100 closes that gap by reusing the
same backend we already trust for app-deps.
Coverage
OSV.dev covers these OS-ecosystems and is updated continuously:
| Distro family | OSV ecosystem |
|---|---|
| Ubuntu | Ubuntu:24.04, Ubuntu:22.04, Ubuntu:20.04, Ubuntu:18.04 |
| Debian | Debian:12, Debian:11, Debian:10 |
| Alpine | Alpine:v3.19, Alpine:v3.18, … |
| Rocky Linux | Rocky Linux:9, Rocky Linux:8 |
| AlmaLinux | AlmaLinux:9, AlmaLinux:8 |
| openSUSE Tumbleweed | openSUSE:Tumbleweed |
| Wolfi | Wolfi |
| Chainguard | Chainguard |
| SUSE SLES 15 | SUSE:SLES15 |
Distros without an OSV ecosystem (Arch, Gentoo, FreeBSD, custom builds) are skipped silently — the Trust Score sub-component blanks rather than penalising.
How it works
- Every 2 hours the
OSPackageCveWorkerreads the latest inventory snapshot per agent, derives an OSV ecosystem fromos_name+os_version, and submits(ecosystem, package_name, version)toPOST https://api.osv.dev/v1/querybatchin chunks of 1000. - Every unique vuln ID returned is fetched once via
GET https://api.osv.dev/v1/vulns/{id}, cached for the cycle. - Each
(agent, package, version, vuln_id)hit is upserted intoos_package_cveswith severity, fixed-version, summary, aliases. - The
/recommendationspage picks them up automatically, and the per-agent CVEs tab UNIONs them with the existing app-dep and Trivy findings.
Trust Score impact
The patch_hygiene component (weight 30%) becomes a 3-way composite
when all three sub-components have data:
application_cves— 50%kernel_currency— 25%os_packages— 25%
When the host is too new for OS-package data to exist yet, the sub-component is blanked (weight 0) — the score stays stable instead of penalising silently.
Privacy
We only send (ecosystem, name, version) triples to OSV.dev. No
hostnames, no tenant IDs, no agent IDs. The exposure is the same as
someone running apt list --installed on the host with shell access.
OSV.dev is operated by Google’s Open Source Security Team under the
Apache 2.0 license; the lookup itself is unauthenticated and free.
Acting on a finding
Each finding is observe-only — per the monsys human-in-the-loop
principle, the hub never auto-runs apt upgrade or any other change.
The /recommendations page shows a per-host preview command:
| Distro | Preview |
|---|---|
| Ubuntu / Debian | sudo apt-get update && sudo apt-get upgrade -y |
| RHEL / Rocky / Alma | sudo dnf upgrade --security -y |
| Alpine | sudo apk update && sudo apk upgrade |
| openSUSE / SLES | sudo zypper patch |
For controlled execution there is the existing package_update EAT
flow on the agent — operator approves the upgrade via TOTP, the EAT
authorises a single-shot apt upgrade <pkg>=<version> with a signed
audit-log entry. That part hasn’t changed.
MCP tool
For Claude Connector users the new tool monsys_list_os_cves exposes
the same data with filters for min_severity, only_with_fix, and
agent_id. Like all detection tools, it is read-only.