Skip to content

SBOM & VEX export

An SBOM lists what is installed. A VEX document states, per vulnerability, whether you are actually affected. monsys generates both per host, from data the agent already reports — no extra scanner, no separate tool.

This is the pairing the EU Cyber Resilience Act (CRA Annex I §5) and NIS2 auditors ask for: the component inventory and the exploitability signal that turns a raw CVE list into an actionable one.

Earlier the SBOM only covered application dependencies. It now has three layers, so it represents the whole host:

LayerSourcepurl example
Application dependenciespackage.json, requirements.txt, composer.lock, go.sum, …pkg:npm/lodash@4.17.21
OS packageslatest inventory snapshot (apt/dpkg/rpm/dnf/apk/zypper/pacman)pkg:deb/ubuntu/openssl@3.0.13?distro=ubuntu
Running kernelkernels_runningpkg:deb/ubuntu/linux-kernel@6.8.0-100-generic?arch=x86_64&distro=ubuntu

Component types are set correctly in both formats: the kernel is OPERATING-SYSTEM (SPDX primaryPackagePurpose) / operating-system (CycloneDX type), OS packages are applications/libraries, app deps are libraries.

GET /api/v1/agents/{id}/sbom?format=spdx-json # SPDX 2.3 (default)
GET /api/v1/agents/{id}/sbom?format=cyclonedx-json # CycloneDX 1.5

Both return a single JSON document with a Content-Disposition attachment name like monsys-sbom-<host>-<date>.spdx.json.

The VEX document is derived from the CVE findings the dashboard already shows — application (inventory_dependency_cves), OS packages (os_package_cves) and the backport-aware kernel pipeline (kernel_cve_findings) — and grounded on operator decisions (cve_suppressions) and the kernel’s distro/mitigation state.

monsys is honest by default (the human-in-the-loop principle): a CVE that matched an installed version is reported affected unless there is positive evidence otherwise. We never silently downgrade to not_affected.

EvidenceOpenVEX statusCycloneDX-VEX state
Operator suppressed the CVE (risk accepted / false positive)not_affected (with your reason as impact_statement)not_affected
Kernel fix backported / finding resolvedfixedresolved
Kernel mitigation active (e.g. Spectre/Meltdown control)not_affected (inline_mitigations_already_exist)not_affected (protected_at_runtime)
Installed at a vulnerable version, no fix/mitigationaffected (with an action_statement)exploitable
Kernel state unknownunder_investigationin_triage

Every affected statement carries a concrete action_statement (e.g. “Upgrade openssl to 3.0.14 or later.”); every not_affected carries a justification or impact statement, as the specs require.

GET /api/v1/agents/{id}/vex?format=openvex # OpenVEX 0.2.0 (default)
GET /api/v1/agents/{id}/vex?format=cyclonedx-vex # CycloneDX-VEX 1.5

Open a server → CVEs tab → the Audit export bar. Four one-click downloads: SBOM (SPDX / CycloneDX) and VEX (OpenVEX / CycloneDX-VEX).

The monthly Audit Pack bundles a vex_statement line per host per vulnerability, using the exact same derivation as the download above — so the signed evidence matches what your operators can pull on demand. Like the rest of the pack it is Ed25519-signed and offline-verifiable.

Everything is generated inside the hub from data the agent already reports. Building the SBOM/VEX sends nothing to third parties. (The underlying CVE matching uses OSV.dev with only (ecosystem, name, version) triples — see OS-package CVE matching.)