CSAF

CSAF 2.0 (Common Security Advisory Framework) is the OASIS standard for machine-readable vendor security advisories, and the format CISA has driven adoption of. Vendors including Red Hat, SUSE, Cisco and Siemens publish their advisories as CSAF.

Supported: CSAF 2.0 JSON. CSAF 1.x used the older CVRF schema and is rejected with a clear message rather than mis-parsed.

One finding per vulnerability and product

A single CSAF advisory routinely covers many products in different states — one patched, another still exposed, a third explicitly unaffected. The parser therefore emits one finding per (vulnerability, product) pair, so each product’s actual status is preserved.

known_not_affected products are imported inactive

product_status.known_not_affected is the vendor explicitly stating a product is not exposed. Importing that as an active finding would turn the vendor’s “you are fine” into work, the same mistake a mishandled VEX statement makes. Those findings are imported inactive and flagged as false positives, with the status recorded in the description.

product_status bucketActive?Disposition
known_affected, first_affected, last_affectedYesActive
known_not_affectedNofalse_p
fixed, first_fixed, recommendedNois_mitigated
under_investigationYesActive, verified=False
anything elseYesActive — a bucket a future revision adds must never silently suppress a real exposure

Product tree resolution

A CSAF product id is never defined in one place. The parser indexes all three mechanisms:

  • full_product_names[] — a flat {product_id, name} list.
  • branches[] — an arbitrarily deep tree. The version lives on a product_version branch, not in the leaf, so the tree is walked and the nearest enclosing version is carried down. Where the leaf name repeats the version (“Generic App 1.0.0”), it is stripped so component_name is just “Generic App” — otherwise the same product would deduplicate differently depending on which shape the advisory used.
  • relationships[] — a synthesised product (“library as a component of app”) whose own full_product_name defines a new product id.

Field mapping

CSAFDefectDojo
vulnerabilities[].cve (else ids[].text, for an embargoed issue)vuln_id_from_tool, unsaved_vulnerability_ids
scores[].cvss_v3.baseSeverityseverity
scores[].cvss_v3.baseScore / vectorStringcvssv3_score / cvssv3
cwe.idcwe
remediations[] filtered to the productmitigation (category, details, url, restart_required)
notes[] of category description/summary/detailsdescription
references[]references
document.tracking.current_release_datedate

scores[] entries are scoped to a product list, so the same CVE can be scored differently per product; each finding gets its own product’s score. An advisory with no score at all becomes Medium, not Info — a published vendor advisory is not informational, and Info would hide it behind a minimum-severity setting.

Sample Scan Data

Sample CSAF files are available at unittests/scans/csaf.

Obtaining an importable file

Unlike a scanner report, CSAF documents are published, not generated by running a tool over a target. A CSAF advisory is authored by a product security team, so there is no command that produces one from your own environment. Obtain them from a vendor’s CSAF distribution:

  • Vendors publish a provider-metadata.json under /.well-known/csaf/ describing their feed.
  • csaf_downloader (the reference Go implementation) mirrors a vendor’s advisories:
csaf_downloader --directory ./advisories https://vendor.example.com
  • Individual advisories can also be downloaded directly from a vendor’s security page.

Validate a document before importing with the same project’s validator:

csaf_validator ./advisories/2026/example-2026-0001.json

The fixtures committed with this parser were authored against the CSAF 2.0 schema and verified with csaf_validator from github.com/gocsaf/csaf/v3 — all three pass schema validation.

Default deduplication hashcode fields

vuln_id_from_tool, component_name, component_version.