Voor platform- + security-engineers · 2026-07-30

Een CISA 2026-conforme SBOM met de hand bouwen: alles wat je zonder monsys doet

De 2026 Minimum Elements maakten van een SBOM een ondertekend, gelicentieerd, machineverifieerbaar artefact. Dit is de volledige handmatige pijplijn voor één Linux-host: inventariseer drie lagen, vul elk verplicht veld, canoniseer en onderteken met Ed25519, en leid dan VEX af. Het is veel.

Ons vorige artikel behandelde wat de CISA 2026 Minimum Elements vereisen. Dit is het eerlijke vervolg: heb je geen monsys, dan is dit wat het echt kost om met de hand een conforme SBOM voor één machine te maken. Doe het één keer en je begrijpt waarom "genereer even een SBOM" geen vinkje is.

We bouwen er een voor een Linux-host. Windows lijkt qua vorm, verschilt qua tooling.

Stap 1: inventariseer drie lagen, niet één

Een machine is niet alleen haar applicatie-afhankelijkheden. Een conforme host-SBOM dekt alles wat een CVE kan dragen:

Applicatie-afhankelijkheden

Parse de lockfile van elk ecosysteem: package-lock.json, requirements.txt, composer.lock, go.sum, enzovoort. Tools als Syft helpen hier, maar het samenvoegen tot één document en het verzoenen van versies blijft jouw werk.

OS-pakketten

Bevraag de pakketbeheerder, één syntaxis per distro-familie.

Debian / Ubuntu:

dpkg-query -W -f='${Package}\t${Version}\t${Architecture}\n'

RPM (RHEL / Fedora / Rocky / Alma):

rpm -qa --qf '%{NAME}\t%{VERSION}-%{RELEASE}\t%{ARCH}\t%{LICENSE}\n'

Alpine:

apk info -v

Zet nu elke regel om in een Package URL. openssl 3.0.13 op Ubuntu 22.04 wordt:

pkg:deb/ubuntu/openssl@3.0.13?arch=amd64&distro=ubuntu-22.04

Zijn de qualifiers verkeerd, dan mist de downstream CVE-matching stilzwijgend.

De draaiende kernel

uname -r   # 6.8.0-100-generic
uname -m   # x86_64

Dat wordt pkg:deb/ubuntu/linux-kernel@6.8.0-100-generic?arch=x86_64&distro=ubuntu. Markeer het daarna als een operating-system-component (CycloneDX type, SPDX primaryPackagePurpose), anders behandelt een scanner je kernel als een npm-bibliotheek.

Stap 2: vul elk verplicht 2026-veld

De standaard is niet "een lijst met namen". Per component ben je nu verschuldigd:

Dan de metadata op documentniveau: Author, Author Signature (Stap 3), Data Format Name en Version, Timestamp (RFC 9557 / RFC 3339), Tool Name en Version, Generation Context (voor / tijdens / na build), en een SBOM Version met semantic versioning.

Stap 3: onderteken het zodat iedereen kan verifiëren

Dit is het deel dat de meeste zelfgemaakte SBOM's overslaan, en het is nu verplicht.

  1. Genereer een sleutel:
openssl genpkey -algorithm ed25519 -out sbom-key.pem
  1. Canoniseer het document met RFC 8785 (JSON Canonicalization Scheme), met de handtekeninghouder verwijderd. Er is geen openssl-vlag voor. JCS sorteert objectsleutels op UTF-16 code unit, gebruikt minimale escaping en een specifiek getalformaat. Je schrijft of importeert een JCS-bibliotheek, en onderteken je de verkeerde bytes, dan wijst elke downstream-verifier de handtekening af.
  2. Onderteken de canonieke bytes met de Ed25519-sleutel.
  3. Bed de handtekening in. CycloneDX heeft een eigen JSF signature-blok; SPDX heeft geen handtekeningveld, dus draag je die in een annotatie op documentniveau.
  4. Publiceer de publieke sleutel op een opvraagbare plek, zodat een derde partij het bestand opnieuw kan canoniseren, je sleutel kan ophalen en het offline kan verifiëren.

Mis één van deze vijf en je hebt een handtekening die niemand anders kan controleren, wat gelijkstaat aan geen handtekening.

Stap 4: leid VEX af, want een lijst is niet het doel

De standaard van 2026 voegt een sectie toe over het koppelen van SBOM's aan security-advisories, met VEX en CSAF expliciet bij naam. De inventaris is dus maar de helft van de oplevering. Voor elk component doe je nu:

  1. Match het tegen een kwetsbaarheidsbron. OSV.dev neemt gebundelde (ecosysteem, naam, versie)-triplets; NVD matcht op CPE.
  2. Bepaal een status per CVE: affected, not_affected, fixed of under_investigation.
  3. Onderbouw het. OpenVEX vereist een action_statement bij affected en een justification of impact_statement bij not_affected. Een gebackporte kernelfix leest als "fixed" ook al ziet de versiestring er nog kwetsbaar uit, dus je hebt distro-backport-bewustzijn nodig of je overrapporteert.
  4. Emitteer OpenVEX of CycloneDX-VEX.

Doe je dit fout in de veilige richting, dan overspoel je je auditor met valse positieven. Doe je het fout in de gemakkelijke richting, dan verberg je stilzwijgend een echte blootstelling.

Stap 5: doe het nu voor altijd, op elke host

De stappen hierboven leveren één SBOM voor één machine op één moment. De standaard vraagt ook om Frequency (opnieuw genereren bij wijziging) en Distribution and Delivery (aanbieden via een API of URL). Dus verpak je de hele pijplijn in een scheduler, sla je de outputs op, ontsluit je een endpoint, roteer en bescherm je de ondertekensleutel, en herhaal je dit voor elke host in de vloot. Elke nieuwe distributie is een nieuwe producer-map en een nieuwe licentie-parse-eigenaardigheid.

De eerlijke rekening

Voor één Linux-host, conform en ondertekend, met de hand:

Dat is een klein project, geen commando.

Of: de monsys-versie

monsys doet al het bovenstaande op basis van data die de agent al rapporteert. Open een host, ga naar het tabblad CVE's, en de Audit-export-balk geeft je SBOM (SPDX 2.3 of CycloneDX 1.5) en VEX (OpenVEX of CycloneDX-VEX), elk ondertekend met onze Ed25519-sleutel en offline verifieerbaar tegen onze gepubliceerde publieke sleutel. Of haal ze rechtstreeks uit de API:

GET /api/v1/agents/{id}/sbom?format=spdx-json
GET /api/v1/agents/{id}/sbom?format=cyclonedx-json
GET /api/v1/agents/{id}/vex?format=openvex

Dezelfde data, dezelfde handtekening, gebundeld in de maandelijkse Audit Pack. Alles wordt gegenereerd binnen een in de EU gehost platform, zonder dat er iets naar derden gaat.


Achtergrond: CISA herschreef de SBOM-regels. Technisch detail: docs.monsys.ai/nl/security/sbom-vex. Eerste vijf servers gratis: monsys.ai/nl/signup.

Terug naar blog