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 (lockfiles)
- OS-pakketten (de pakketdatabase van de distributie)
- De draaiende kernel
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:
- Component Producer. Wijs elke distributie toe aan een echte producent: Ubuntu aan Canonical Ltd., Debian aan het Debian Project, Alpine aan Alpine Linux, enzovoort. Waar je het echt niet kunt bepalen, moet je
NOASSERTIONschrijven, niet gokken. - Component Identifiers. Minstens één purl of CPE, zoals hierboven.
- Component License. Een SPDX-licentie-identifier. Op Debian betekent dat
/usr/share/doc/<pkg>/copyrightparsen, wat vrije tekst is, en dat mappen naar een SPDX-ID. Op RPM krijg je%{LICENSE}, wat dichterbij komt maar nog steeds niet altijd een geldige SPDX-expressie is. - Component Hash + Algorithm. Een hash van het artefact, met een IANA-geregistreerde algoritmenaam. Hier zit de valstrik: een metadata-inventaris heeft de originele artefact-bytes niet. Je downloadt en hasht elk artefact, of je registreert de hash als echt onbekend. Er een verzinnen is erger dan er geen opnemen, en het element "Explicitly Identifying Unknown Information" van de standaard vereist dat je dat eerlijk zegt.
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.
- Genereer een sleutel:
openssl genpkey -algorithm ed25519 -out sbom-key.pem
- 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. - Onderteken de canonieke bytes met de Ed25519-sleutel.
- Bed de handtekening in. CycloneDX heeft een eigen JSF
signature-blok; SPDX heeft geen handtekeningveld, dus draag je die in een annotatie op documentniveau. - 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:
- Match het tegen een kwetsbaarheidsbron. OSV.dev neemt gebundelde
(ecosysteem, naam, versie)-triplets; NVD matcht op CPE. - Bepaal een status per CVE:
affected,not_affected,fixedofunder_investigation. - Onderbouw het. OpenVEX vereist een
action_statementbijaffecteden een justification ofimpact_statementbijnot_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. - 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:
- 3 inventarisbronnen, samengevoegd en ontdubbeld
- purl-constructie met correcte distro-qualifiers
- een distributie-naar-producent-mapping
- een licentietekst-naar-SPDX-ID-mapping
- een eerlijk onbekende-hash-beleid
- 9 documentmetadata-velden
- een Ed25519-sleutel, een JCS-canoniseerder en een inbed-en-publiceer-pad
- een VEX-afleiding met onderbouwing per CVE en backport-bewustzijn
- een scheduler, opslag en een leverendpoint
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.