Capa across the supply-chain governance stack

Five frameworks set the rules for how software-bearing organisations report, audit, and remediate their codebases: the EU Cyber Resilience Act, NIS2, DORA, NIST SSDF, and OWASP SCVS. This page maps which Capa artefacts answer which clauses. It is descriptive rather than legal: the mapping is one person's reading of each instrument, and any conformity decision belongs to an auditor or a supervisory authority, not to a compiler manual.

The five frameworks

Limits of the language's reach. Most of what these frameworks demand is organisational: vulnerability disclosure processes, incident notification timelines, supplier due diligence, conformity assessment. None of that is in Capa's reach. What Capa contributes is a narrow slice of the technical artefacts the organisational layer consumes. Each fit below is marked direct (the artefact satisfies the clause on its own), indirect (Capa enables it but the organisation still has work to do), or partial (Capa contributes without closing the requirement).

What the compiler emits

Every artefact below is generated from the same source the type checker reads, in one pass, with no external scanner. The capability discipline puts the authority graph in the type system; the emitters serialise it.

Capa artefactFlagWhat it carries
Capability manifest--manifestPer-function declared capabilities, attributes, signatures, declassification sites, user-defined capability declarations
CycloneDX 1.5 SBOM--cyclonedxThe manifest wrapped in CycloneDX with per-function properties[] and an optional vulnerabilities[] array
SPDX 2.3 SBOM--spdxSame metadata, SPDX annotations[] shape, Linux Foundation alignment
CycloneDX VEX--vexPer-function exploitability claims from @vex(cve, status, justification, detail) attributes
SLSA L1 provenance--provenancein-toto Statement v1 plus SLSA Provenance v1.0 predicate, source SHA-256
Audit pipelineexamples/sbom_capability_audit.capaSBOM vs policy diff, structural
SBOM diff toolexamples/sbom_diff.capaTwo SBOMs in, per-function widening / narrowing / added / removed out
Machine-checked soundnessdocs/semantics.md, proofs/λcap calculus with four Agda-checked soundness theorems, plus a machine-checked noninterference proof for the IFC layer

And how each maps across the five frameworks:

Capa outputCRA Annex INIS2 Art. 21DORANIST SSDFOWASP SCVS
ManifestI-II(1) direct21(2)(d) indirectArt. 8 indirectPS.1 indirectDomain 1 partial
CycloneDX SBOMI-II(1) direct21(2)(d) directArt. 8 directPS.3 directDomain 2 direct
SPDX SBOMI-II(1) direct21(2)(d) directArt. 8 directPS.3 directDomain 2 direct
CycloneDX VEXI-II(2) partialArt. 23 indirectArts. 17-19 partialRV.1, RV.2 directDomain 5 direct
SLSA L1 provenanceI-I(2)(f) indirect21(2)(d) indirectArts. 28-30 partialPS.2 partial, PS.3 partialDomain 6 direct
Audit pipelineI-II(1) indirect21(2)(d) directArts. 28-30 directPO.5 indirectDomain 1 partial
SBOM diff toolI-II(2) indirect21(2)(d) partialArts. 17-19 partialRV.1 partialDomain 2 partial
Machine-checked soundnessI-I(2)(b) indirectn/an/aPW.4 indirectn/a

Reproducible SBOMs: rebuild and diff byte-for-byte

The four supply-chain artefacts (--cyclonedx, --spdx, --vex, --provenance) are byte-reproducible. Every identifier they carry, the CycloneDX serialNumber, the SPDX documentNamespace, the provenance invocationId, is derived deterministically from the source file's SHA-256, so two builds of the same source produce the same identifiers on any machine and operating system. The one field that would otherwise vary is the build timestamp; set SOURCE_DATE_EPOCH (the reproducible-builds.org convention) to pin it.

$ SOURCE_DATE_EPOCH=1609459200 capa --cyclonedx app.capa > a.json
$ SOURCE_DATE_EPOCH=1609459200 capa --cyclonedx app.capa > b.json
$ diff a.json b.json   # empty: byte-for-byte identical

This makes "recompile and compare byte-for-byte" a concrete check an auditor can run: the SBOM is a deterministic function of the source, not of the machine that produced it. When SOURCE_DATE_EPOCH is unset, the timestamps record real wall-clock time, so an interactive build still says when it ran; determinism is opt-in via the standard variable, and a malformed value fails loudly rather than silently falling back. It is strong evidence for the CRA build-integrity and NIS2 supplier-assessment clauses, where a verifier needs to confirm an artefact came from the source it claims.

CRA: the Cyber Resilience Act

The CRA entered into force on 10 December 2024 and applies most of its obligations from 11 December 2027. It binds manufacturers placing products with digital elements on the EU market. The clauses that matter most for a compiler are Annex I Part I (the essential cybersecurity requirements: secure by default, attack-surface minimisation, data minimisation, exploitation mitigation, integrity protection), Annex I Part II (1) (a machine-readable SBOM covering at least top-level dependencies), and Annex I Part II (2)-(7) (vulnerability handling processes).

The strongest fits:

What Capa does not address: vulnerability disclosure processes, the 24-hour incident notification window, security-update distribution, and the conformity assessment paperwork itself. The article-by-article CRA deep dive lives at docs/cra.md.

NIS2 and DORA: the operator side

NIS2 (transposition deadline 17 October 2024) is the operator-side counterpart to the CRA's manufacturer framing. Article 21(2)(d) is the heart of its supply-chain ask: an essential or important entity has to assess the security of its direct suppliers. The CycloneDX or SPDX SBOM a Capa-using supplier ships gives that operator a per-function authority surface; the SBOM diff tool detects supplier widening across releases; the audit pipeline verifies the supplier's declarations against an internal policy. Incident reporting under Article 23 and the board-level accountability under Article 20 sit outside what a compiler can affect.

DORA (applies since 17 January 2025) binds financial entities plus critical ICT third-party providers. Article 8 (identification of ICT-supported business functions and assets) is served directly by the SBOMs; per-function metadata gives finer-grained inventory than the financial sector is used to. Articles 28-30 (ICT third-party risk) are served by the audit pipeline and the SBOM diff tool, and the provenance attestation supports the due-diligence-on-provider requirement. The business-continuity bulk of DORA, and resilience testing under Articles 24-27, are out of a language's reach.

NIST SSDF and OWASP SCVS

NIST SP 800-218 (SSDF) is the US federal baseline cited by EO 14028; federal suppliers are pulled in through procurement. Where Capa lands, by practice:

PracticeWhat Capa provides
PS.1 (Protect all forms of code)Manifest declares the access boundary per function; widening is loud in diffs. Repository access control stays organisational
PS.2 (Verify release integrity)SLSA L1 provenance names the builder, the source, and the parameters, with the source SHA-256. Signing is external at L1
PS.3 (Archive and protect each release)CycloneDX, SPDX, and provenance bundled as a release-artefact set; PS.3.2 names provenance data and SBOMs explicitly. Archival itself stays organisational
PW.4 (Reuse well-secured software)Capability discipline rules out ambient-authority abuse in third-party Capa code
RV.1 (Identify and confirm vulnerabilities)VEX entries make per-function exploitability assertions; SBOM diff catches supplier widening
RV.2 (Assess, prioritise, remediate)VEX state and justification shape feeds standard tooling

OWASP SCVS is the cleanest fit of the five: every Capa artefact maps directly to one of its six domains (inventory, SBOM, build environment, package management, component analysis, pedigree and provenance). An organisation using Capa can plausibly claim SCVS L1 across Domains 1, 2, 5, and 6 without additional work, and L2 on Domains 2 and 6 with the existing artefacts. Domain 3 (build environment) is a toolchain concern outside the language.

The triangle the frameworks all reference

Supply-chain governance literature converges on three artefacts. The SBOM describes what is in the box. VEX describes how the box is affected by known vulnerabilities. Provenance describes where the box came from. The CRA names all three in Annex I Part II; NIS2 and DORA touch them through inventory and supplier-risk clauses; NIST SSDF allocates a practice to each; OWASP SCVS gives each its own domain.

Capa emits all three from one source, at per-function granularity for the first two. The alternative today is to combine a package-level SBOM generator, a hand-written VEX, and a separate signing and attestation step. Capa packages the three together at finer granularity, with each artefact's contents grounded in the type system rather than in a separate analyser's heuristics.

See it in practice

capa_claimdesk
An enterprise expense-reimbursement engine that puts the regulated parts beyond reach: the employee IBAN is information-flow-controlled and reaches the tamper-evident, HMAC-chained audit ledger only through an audited declassify (the chain re-verified in constant time), the payment authorization is a linear use-once token, and the claim lifecycle is a typestate. Every guarantee is proved by construction in the emitted SBOM, with negative cases that must not compile.
capa_paymentguard
A payment-security core (PCI DSS / PSD2 framing) that ships a generated conformity pack in conformity/: capability manifest, CycloneDX and SPDX SBOMs, VEX, SLSA provenance, and a CONFORMITY.md walking an auditor through them. The compiler proves a card number cannot reach a log or the network unless it is masked through an audited declassify, and the SBOM lists every disclosure point.
capa_cra_template
A starting template for a CRA-oriented Capa project: a small program plus the policy file and generation steps that produce the same conformity-pack layout for your own code.
capa_governance_pack
An evidence-pack generator, itself written in Capa. It takes a CycloneDX SBOM, a governance policy, and a VEX exclusions list, then turns the compiler's machine-readable artefacts into a regulator-readable Markdown audit pack plus a JSON attestation that a GRC platform can ingest. It diffs each function's emitted capabilities against the policy allow-list, tracks documented exceptions as VEX entries, and reports a compliance score, complementing the CRA template by carrying the same evidence into a GRC workflow.

The hands-on walkthrough of generating each artefact from a small program is tutorial chapter From source to SBOM.

Caveats, honestly

The full mapping document, with primary-source links for all five instruments, is docs/regulatory.md in the compiler repository.

Generate the artefacts yourself