Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions docs/SUPPLY-CHAIN.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ decision record is [ADR 0149](adr/0149-multi-ecosystem-sbom-vex-and-sbom-quality
|---|---|---|
| `messagefoundry-*.whl` / `*.tar.gz` | The Python engine (wheel + sdist) | GitHub release + PyPI |
| `messagefoundry-sbom.cdx.json` | **CycloneDX SBOM** of the engine — license-complete, from the hash-locked core runtime, lifecycle = `build` | GitHub release |
| `messagefoundry-vex.openvex.json` | **OpenVEX** — our per-CVE exploitability assessments | GitHub release |
| `messagefoundry-vex.openvex.json` | **OpenVEX** — the document carrying our exploitability assessment for a CVE, once one has been made | GitHub release |
| `*.sigstore*` bundles | Sigstore signatures for the wheel, sdist, **SBOM, and VEX** | GitHub release |
| PEP 740 attestations | PyPI-side provenance (Trusted Publishing) | PyPI |
| SLSA build provenance | in-toto attestation binding each artifact (incl. SBOM + VEX) to the source commit | GitHub attestations / Sigstore bundle |
Expand Down Expand Up @@ -59,21 +59,27 @@ Attestations, and our releases, if you standardize on one tool across ecosystems

## Using the SBOM + VEX

The SBOM (CycloneDX 1.6) is a machine-readable inventory: components, versions, PackageURLs, hashes, and
**licenses**. Feed it to your own tooling:
The SBOM (CycloneDX 1.6) is a machine-readable inventory carrying at least a name, version, PackageURL and
**license** for every component. It does **not** carry per-component file hashes — the generator we run does
not emit them (see [How the SBOMs are generated](#how-the-sboms-are-generated-for-auditors)) — so use it as an
inventory, not as an integrity check on the components it lists. "Hash-locked" elsewhere on this page refers
to the lock file the inventory is built from, not to a field inside the SBOM. Feed it to your own tooling:

```bash
# Scan the SBOM for known CVEs, applying our VEX to suppress vulnerabilities we've assessed as
# not-affected/fixed — so you triage real risk, not unreachable CVEs:
# Scan the SBOM for known CVEs. --vex applies whatever assessments our VEX carries; --show-suppressed
# lists what was suppressed, so a run with nothing to apply is visibly a no-op:
trivy sbom messagefoundry-sbom.cdx.json --vex messagefoundry-vex.openvex.json --show-suppressed

# Or score the SBOM's completeness (0-10, NTIA minimum elements):
sbomqs score -b messagefoundry-sbom.cdx.json
```

**Do not demand a zero-CVE "clean scan."** Per CISA's *Minimum Requirements for VEX* and NTIA's
*Software Consumers Playbook*, the correct posture is to accept a valid VEX assessment. Our VEX
(`security/vex/README.md`) records, per CVE, whether the vulnerable code is reachable in MessageFoundry.
*Software Consumers Playbook*, the correct posture is to accept a valid VEX assessment. Our VEX is the
`messagefoundry-vex.openvex.json` release asset above. Where we have assessed a CVE, its statement records
whether the vulnerable code is reachable in MessageFoundry and carries an OpenVEX `justification`. Where we
have not, the document says nothing about that CVE and your scanner's finding stands unsuppressed — see
[`security/vex/README.md`](../security/vex/README.md) for the assessment process and when a statement is added.

## How the SBOMs are generated (for auditors)

Expand Down
7 changes: 5 additions & 2 deletions scripts/security/sbom_finalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@

WHY THIS EXISTS (ADR 0149). The SBOM generators we run — ``cyclonedx-py environment`` (Python),
``@cyclonedx/cyclonedx-npm`` (the VS Code extension), and ``trivy image`` (the container) — emit a
CycloneDX BOM with components, hashes, licenses, and ``metadata.tools`` (the generating tool, i.e.
the draft-2025 CISA "Tool Name" minimum element). Two gaps remain that this closes:
CycloneDX BOM carrying at least components, licenses, and ``metadata.tools`` (the generating tool, i.e.
the draft-2025 CISA "Tool Name" minimum element). Per-component *hashes* are NOT among them for the
Python SBOM: ``cyclonedx-py environment`` emits none at all, so do not describe the finalized artifact
as hash-bearing (docs/SUPPLY-CHAIN.md says so to operators, and the two must not drift apart again).
Two gaps remain that this closes:

1. None of them set ``metadata.lifecycles`` — the CycloneDX field that records WHERE in the SDLC
the BOM was produced. That maps to CISA's "Build" SBOM Type and the draft-2025 CISA "Generation
Expand Down
Loading