Skip to content

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:

  1. Application dependencies — OSV.dev against package.json, requirements.txt, composer.lock, go.sum. Shipped in schema 035.
  2. Container images — Trivy against image manifests. Shipped in schema 035.
  3. 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 familyOSV ecosystem
UbuntuUbuntu:24.04, Ubuntu:22.04, Ubuntu:20.04, Ubuntu:18.04
DebianDebian:12, Debian:11, Debian:10
AlpineAlpine:v3.19, Alpine:v3.18, …
Rocky LinuxRocky Linux:9, Rocky Linux:8
AlmaLinuxAlmaLinux:9, AlmaLinux:8
openSUSE TumbleweedopenSUSE:Tumbleweed
WolfiWolfi
ChainguardChainguard
SUSE SLES 15SUSE: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

  1. Every 2 hours the OSPackageCveWorker reads the latest inventory snapshot per agent, derives an OSV ecosystem from os_name + os_version, and submits (ecosystem, package_name, version) to POST https://api.osv.dev/v1/querybatch in chunks of 1000.
  2. Every unique vuln ID returned is fetched once via GET https://api.osv.dev/v1/vulns/{id}, cached for the cycle.
  3. Each (agent, package, version, vuln_id) hit is upserted into os_package_cves with severity, fixed-version, summary, aliases.
  4. The /recommendations page 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:

DistroPreview
Ubuntu / Debiansudo apt-get update && sudo apt-get upgrade -y
RHEL / Rocky / Almasudo dnf upgrade --security -y
Alpinesudo apk update && sudo apk upgrade
openSUSE / SLESsudo 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.