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
- Cyber Resilience Act (Regulation (EU) 2024/2847): the EU's manufacturer-side rule for products with digital elements.
- NIS2 (Directive (EU) 2022/2555): the operator-side counterpart, scoped to essential and important entities across eighteen sectors.
- DORA (Regulation (EU) 2022/2554): the financial-sector operational resilience regulation. Only the cybersecurity articles are in scope here.
- NIST SSDF (SP 800-218): the US federal baseline for secure software development cited by Executive Order 14028.
- OWASP SCVS: the vendor-neutral Software Component Verification Standard, with three levels.
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 artefact | Flag | What it carries |
|---|---|---|
| Capability manifest | --manifest | Per-function declared capabilities, attributes, signatures, declassification sites, user-defined capability declarations |
| CycloneDX 1.5 SBOM | --cyclonedx | The manifest wrapped in CycloneDX with per-function properties[] and an optional vulnerabilities[] array |
| SPDX 2.3 SBOM | --spdx | Same metadata, SPDX annotations[] shape, Linux Foundation alignment |
| CycloneDX VEX | --vex | Per-function exploitability claims from @vex(cve, status, justification, detail) attributes |
| SLSA L1 provenance | --provenance | in-toto Statement v1 plus SLSA Provenance v1.0 predicate, source SHA-256 |
| Audit pipeline | examples/sbom_capability_audit.capa | SBOM vs policy diff, structural |
| SBOM diff tool | examples/sbom_diff.capa | Two SBOMs in, per-function widening / narrowing / added / removed out |
| Machine-checked soundness | docs/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 output | CRA Annex I | NIS2 Art. 21 | DORA | NIST SSDF | OWASP SCVS |
|---|---|---|---|---|---|
| Manifest | I-II(1) direct | 21(2)(d) indirect | Art. 8 indirect | PS.1 indirect | Domain 1 partial |
| CycloneDX SBOM | I-II(1) direct | 21(2)(d) direct | Art. 8 direct | PS.3 direct | Domain 2 direct |
| SPDX SBOM | I-II(1) direct | 21(2)(d) direct | Art. 8 direct | PS.3 direct | Domain 2 direct |
| CycloneDX VEX | I-II(2) partial | Art. 23 indirect | Arts. 17-19 partial | RV.1, RV.2 direct | Domain 5 direct |
| SLSA L1 provenance | I-I(2)(f) indirect | 21(2)(d) indirect | Arts. 28-30 partial | PS.2 partial, PS.3 partial | Domain 6 direct |
| Audit pipeline | I-II(1) indirect | 21(2)(d) direct | Arts. 28-30 direct | PO.5 indirect | Domain 1 partial |
| SBOM diff tool | I-II(2) indirect | 21(2)(d) partial | Arts. 17-19 partial | RV.1 partial | Domain 2 partial |
| Machine-checked soundness | I-I(2)(b) indirect | n/a | n/a | PW.4 indirect | n/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:
- Part II (1), SBOM: CycloneDX and SPDX cover the requirement twice over, with per-function granularity the clause does not even ask for.
- Part I (2)(b), secure by default: the capability discipline enforces it structurally. A function holds no authority it did not declare.
- Part I (2)(g), data minimisation: least authority is the language model, and the information-flow layer adds machine-checked disclosure records (
declassification_sites). - Part I (2)(j), attack-surface minimisation: the function's signature is the declared attack surface.
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:
| Practice | What 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 aCONFORMITY.mdwalking an auditor through them. The compiler proves a card number cannot reach a log or the network unless it is masked through an auditeddeclassify, 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
- Compliance with any of the five frameworks is an organisational outcome that combines technical artefacts with processes. Capa contributes evidence, not compliance.
- The mapping above is one reading of each instrument. An organisation's auditors or supervisory authority may classify the same artefact differently. Treat it as a starting point for an internal gap analysis, not as a legal opinion.
- These frameworks evolve: CRA implementing acts are still being drafted in 2026, NIS2 transposition varies by Member State, and NIST SSDF will see further revisions. The mapping reflects the state of the five as of mid-2026.
- Capa is a one-person project at 1.5. The artefact outputs are stable enough to integrate into compliance pipelines, but the project has not been through the independent assurance a production deployment in a regulated industry would expect.
The full mapping document, with primary-source links for all five instruments, is docs/regulatory.md in the compiler repository.