# CRA Compliance — Standards Reverse Map
This document maps every compliance check sbom-tools surfaces under
`--standard cra` (and the related Article 24 / BSI / Annex III/IV
profiles) to the underlying regulation, harmonised standard, and
ENISA / industry guidance. Use it to:
- **Auditors / notified bodies**: locate the regulatory text behind each
finding by Article number or Annex reference.
- **Engineers**: see which sidecar field (`CraSidecarMetadata`), SBOM
field, or CycloneDX 1.6 [attestation](#attestation-evidence-cyclonedx-16-declarations)
clears each violation.
- **GRC / dashboards**: cross-reference SARIF `properties.standardIds`
and `properties.standardHelpUris` to produce control-mapping reports.
> Generated and maintained alongside the sbom-tools source tree.
> If a check or article moves, send a PR — the reverse map is the
> single source of truth for both human readers and the
> `rule_meta()` registry (surfaced via `Violation::registry_standard_refs()`).
## CRA timeline anchors
| 2024-12-10 | CRA enters into force (Regulation (EU) 2024/2847) |
| 2026-09-11 | Article 14 reporting obligations apply (`ComplianceLevel::CraPhase1`) — Art. 71(2) |
| 2027-12-11 | Regulation applies in full (`ComplianceLevel::CraPhase2`) — Art. 71(2) |
## Compliance levels
| `CraPhase1` | `cra-phase1`, `cra-2026` | CRA Phase 1 — Art. 14 reporting obligations (apply from 2026-09-11) |
| `CraPhase2` | `cra` (default CRA meaning), `cra-phase2` | Full CRA compliance (regulation fully applies from 2027-12-11) |
| `CraOssSteward` | `oss-steward`, `cra-oss-steward`, `cra-oss`, `cra-art24`, `art24` | Article 24 lighter profile for open-source software stewards |
| `BsiTr03183_2` | `bsi`, `tr-03183`, `tr03183`, `bsi-tr-03183-2` | BSI TR-03183-2 (German national CRA-aligned baseline) |
| `Cnsa2` | `cnsa2`, `cnsa-2`, `cnsa_2`, `cnsa2.0` | NSA CNSA 2.0 (post-quantum mandate for US national-security systems) |
| `NistPqc` | `pqc`, `nist-pqc`, `nist_pqc` | NIST IR 8547 + FIPS 203/204/205 (PQC migration) |
The `--cra-product-class` flag (or sidecar `productClass`) drives the
[CRA-P3.2 calibration table](#cra-p32-product-class-severity-calibration)
that scales severity for vendor-hash, EOL, cycles, DoC, EUCC, PSIRT,
and module-attestation checks.
## Reverse map
Each row maps a sbom-tools `Violation::requirement` string to its
regulatory anchor, the harmonised-standard requirement ID
(prEN 40000-1-3 where known), the BSI section, and the canonical URL
that ends up in SARIF `properties.standardHelpUris`.
### CRA Article 13 (essential requirements & SBOM-related obligations)
> Rule citations were re-anchored in 2026-07: the SBOM-facing checks now
> cite the paragraphs and Annex points that actually carry each
> obligation in Reg. (EU) 2024/2847 (e.g., the machine-readable SBOM
> mandate lives in Annex I Part II (1), the vulnerability-reporting
> contact in Art. 13(17), and manufacturer identification in
> Art. 13(16)). The BSI column uses TR-03183-2 v2.1.0 numbering.
| `CRA Art. 13(2): Documented risk assessment` | Art. 13(2) | — | — | `riskAssessmentUrl` + `riskAssessmentMethodology` |
| `CRA Art. 13(7) / Annex I Part II (1): SBOM freshness` | Art. 13(7); Annex I Part II (1) | PRE-7-RQ-04 | §3.1 | regenerate SBOM on each release |
| `CRA Annex I Part II (1): Machine-readable SBOM format` | Annex I Part II (1) | PRE-7-RQ-04 | §4 | parse-time check (CycloneDX 1.4+ / SPDX 2.3+) |
| `CRA Art. 13(5): Third-party due diligence (license tracking)` | Art. 13(5) | PRE-7-RQ-05 | §5.2.2 | populate component `license` fields |
| `CRA Art. 13(17): Vulnerability disclosure contact` | Art. 13(17); Annex I Part II (6); Annex II (2) | RLS-2-RQ-01 | §5.2.5 (opt.) | `securityContact` / `vulnerabilityDisclosureUrl` |
| `CRA Annex I Part II (5): Coordinated vulnerability disclosure policy` | Annex I Part II (5); Art. 13(8) | RLS-2-RQ-02 | — | `coordinatedDisclosurePolicyUrl` |
| `CRA Art. 13(8): Support period / lifecycle management` | Art. 13(8) | PRE-7-RQ-06 | — | `supportEndDate` + EOL enrichment |
| `CRA Art. 13(8) / 13(19): Support period disclosure` | Art. 13(8); Art. 13(19); Annex II (7) | PRE-7-RQ-06 | — | `supportEndDate` |
| `CRA Annex I Part II (1): Documented vulnerability information` | Annex I Part II (1) | RLS-2-RQ-04 | — | OSV / KEV / VEX enrichment |
| `CRA Annex II (7): Component lifecycle monitoring/status` | Art. 13(8); Annex II (7) | PRE-7-RQ-06 | — | EOL enrichment + transitive supplier coverage |
| `CRA Art. 13(15): Product identification` | Art. 13(15); Annex II (3) | PRE-7-RQ-06 | §5.2.2 | SBOM `metadata.component.name` + sidecar `productName` |
| `CRA Annex I Part II (1): Component version` | Annex I Part II (1) | PRE-7-RQ-06 | §5.2.2 | component `version` fields |
| `CRA Annex I Part II (1): Component supplier information` | Annex I Part II (1) | PRE-7-RQ-03 | §5.2.2 | component `supplier` fields |
| `CRA Annex I Part II (4): Vulnerability metadata completeness` | Annex I Part II (4) | — | — | vulnerability severity/CVSS + remediation detail |
| `CRA Art. 13(16): Manufacturer identification` | Art. 13(16); Annex II (1) | — | §5.2.1 | `manufacturerName` + `manufacturerEmail` |
### CRA Article 14 (reporting obligations, applicable from 2026-09-11)
| `CRA Art. 14: PSIRT contact for external vulnerability reports` | Art. 14 | RLS-2-RQ-03 | `psirtUrl` |
| `CRA Art. 14(2)(a): 24-hour early-warning channel` | Art. 14(2)(a) / 14(4)(a) | RLS-2-RQ-03 | `earlyWarningContact` |
| `CRA Art. 14(2)(b): 72-hour notification channel` | Art. 14(2)(b) / 14(4)(b) | RLS-2-RQ-03 | `incidentReportContact` |
| `CRA Art. 14(7): ENISA single reporting platform` | Art. 14(7) | RLS-2-RQ-03-RE | `enisaReportingPlatformId` |
Pre-deadline findings are emitted as `Info`; post-deadline they become
`Warning` (or `Error` at `ImportantClass2`/`Critical` per the
[product-class calibration](#cra-p32-product-class-severity-calibration)).
The 2026-09-11 deadline is compared against the *evaluation instant* — the
wall clock by default, or `--as-of <RFC 3339>` for reproducible CI runs.
Art. 14(7) is the exception: the ENISA single reporting platform has no
published endpoint yet, so the missing-`enisaReportingPlatformId` finding
stays `Info` on both sides of the deadline.
### CRA Annexes
| `CRA Annex I Part II / prEN 40000-1-3 [PRE-7-RQ-07-RE]: Vendor hash carry-through` | Annex I Part II | PRE-7-RQ-07-RE | strong (SHA-256+) hash on vendor-supplied components |
| `CRA Annex I / prEN 40000-1-3 [PRE-7-RQ-07]: Unique component identifier` | Annex I | PRE-7-RQ-07 | PURL / CPE / SWID / SWHID on each component |
| `CRA Annex I Part II: Supply chain transparency` | Annex I Part II | PRE-7-RQ-01,03 | supplier on direct + transitive deps |
| `CRA Annex I Part I (2)(f): Document signature/integrity` | Annex I Part I (2)(f) | — | serial number / digital signature / attestation hash |
| `CRA Annex I Part I (2)(f): Component integrity information (hash)` | Annex I Part I (2)(f) | — | cryptographic hash (SHA-256+) per component |
| `CRA Annex IV: EUCC reference (Common Criteria certificate)`| Annex IV | — | sidecar EUCC evidence fields, a `Certification`/`Attestation` external ref with `eucc`/`common-criteria` URL, or a [CDXA attestation](#attestation-evidence-cyclonedx-16-declarations) naming EUCC / Common Criteria |
| `CRA Annex VII: Technical documentation` | Annex VII | — | run `sbom-tools cra-docs <sbom> --output dossier/` |
| `CRA Annex V: EU Declaration of Conformity reference` | Annex V | — | `Attestation`/`Certification` external ref OR `ceMarkingReference` |
| `CRA Annex VIII: <Module> attestation reference` | Annex VIII (Module B+C/H/EUCC) | — | Module-specific `Attestation`/`Certification` external ref |
| `CRA prEN 40000-1-3 [PRE-8-RQ-02]: Hardware component inventory` | Annex I Part II | PRE-8-RQ-02 | producer + identifier + firmware version on hardware |
### Article 24 — open-source software steward floor
| `CRA Art. 24: Vulnerability-handling process (steward floor)` | Art. 24 | `SecurityContact` / `Advisories` / `VulnerabilityAssertion` external ref OR `psirtUrl` / `vulnerabilityDisclosureUrl` |
| `CRA Annex I Part II (5): Coordinated vulnerability disclosure policy` (relaxed to Warning under steward) | Annex I Part II (5) | `Advisories` external ref OR `coordinatedDisclosurePolicyUrl` |
Article 24 *suppresses* manufacturer-only checks (Art. 13(16) email,
Annex V DoC, Annex VIII attestation, Article 14 channels, hardware
[PRE-8-RQ-02], vendor-hash carry-through).
## CRA-P3.2 product-class severity calibration
When `--cra-product-class` (or sidecar `productClass`) is set, the
severity of certain checks scales per Annex III/IV class. Selecting a
class also implies a default conformity-assessment route (Annex VIII),
overridable via sidecar `conformityAssessmentRoute`.
| Vendor-hash coverage threshold | 50% | 80% | 80% | 100% |
| Vendor-hash severity | Warning | Warning | Error | Error |
| EOL components | Warning | Warning | Error | Error |
| Cycles | Warning | Warning | Error | Error |
| Annex V DoC reference | Info | Warning | Error | Error |
| EUCC reference | n/a | n/a | Info | Error |
| PSIRT documented | Warning | Warning | Error | Error |
| Module attestation reference | n/a | Warning (B+C) | Error (B+C/H) | Error (EUCC) |
Default conformity routes per class:
| Default | Module A (self-assessment) |
| ImportantClass1 | Module A (self-assessment, B+C optional) |
| ImportantClass2 | Module B+C |
| Critical | EUCC |
## Attestation evidence (CycloneDX 1.6 `declarations`)
Added 2026-07: the CRA checks also read machine-readable CDXA evidence.
On a CycloneDX document with `specVersion >= 1.6` carrying a root-level
`declarations` block plus `definitions.standards`, a standard whose
name/description/owner mentions the *Cyber Resilience Act* (or carries the
bare token `cra`) is classified into the CRA rule family, and an
attestation that fully supports one of its requirements can clear a CRA
check on its own. The EUCC-specific rows need the stricter subset: a
CRA-family standard that *also* names EUCC / Common Criteria.
Every sidecar field and external-reference path listed in the reverse map
above remains valid as the self-declared fallback, and a document with no
`declarations` behaves exactly as before — including byte-identical
violation messages.
### What attestation evidence reaches
| `SBOM-CRA-ANNEX-IV` — EUCC / Common Criteria reference (only fires at Important-2 / Critical) | yes | CRA-family standard that also names EUCC / Common Criteria |
| `SBOM-EUCC-CERTREF` (under `--standard eucc`) | yes | same as above |
| `conformity_summary` → "EU Declaration of Conformity" row | yes | any CRA-family attestation |
| `conformity_summary` → Module B / Module C / Module H rows | yes | any CRA-family attestation |
| `conformity_summary` → EUCC certificate + Target-of-Evaluation rows | yes | CRA-family standard that also names EUCC / Common Criteria |
| `SBOM-CRA-ANNEX-V` — Annex V DoC violation | no | `Attestation`/`Certification` external ref or sidecar `ceMarkingReference` |
| `SBOM-CRA-ANNEX-VIII` — module attestation violation | no | `Attestation`/`Certification` external ref |
| `SBOM-EUCC-PP` / `-TOE` / `-ITSEF` / `-VALIDITY` | no | dedicated sidecar EUCC fields |
| `SBOM-CRA-ART-14` channels + the `conformity_summary` PSIRT row | no | sidecar fields |
The `conformity_summary` block is the Annex VIII checklist emitted next to
`violations` by `validate --standard cra -o json`. It only appears once a
product class is pinned — via `--cra-product-class` or the sidecar
`productClass` — since the class picks the conformity route whose rows are
listed. A row strengthened by attestation names the level it was satisfied
at:
```text
Annex V — manufacturer's signed declaration. Provide via Attestation/Certification
external ref or sidecar ceMarkingReference. Satisfied by machine-readable CDXA
attestation (signature-present evidence); external-reference/sidecar presence
remains the self-declared fallback.
```
### When an attestation counts (fail-closed)
All of the following must hold at the evaluation instant (wall clock, or
`--as-of`):
- the attestation map entry declares a full `conformance.score` (`1.0`) —
any score below 1.0 is partial and never auto-satisfies, and a missing
score fails closed too;
- the entry carries no counter-claims and cites at least one claim;
- a cited claim resolves, targets a resolvable element, carries no
counter-evidence, and cites at least one resolvable evidence item that is
fresh (created at or before the instant, and not past its `expires`).
Unresolvable refLinks are kept as dangling and can never help satisfy a
requirement. When a matching attestation exists but trips one of these
gates, the violation still fires and the message names the reason:
```text
[CRA Annex IV / EUCC] Product class Critical requires (or strongly recommends)
a reference to a Common Criteria / EUCC certificate or Target of Evaluation
— CDXA attestation covering an EUCC / Common Criteria certification found but
rejected: declared conformance is partial (score 0.5); partial conformance
never auto-satisfies
```
### Structural verification only
**No signature is ever cryptographically verified.** JSF signature objects
on the declarations, attestations, claims, evidence, affirmation, and
signatories are parsed for *presence* — algorithm, `keyId`, signer count,
signatory identity — and nothing more. The evidence ladder is
`SelfDeclared < Structural < SignaturePresent < SignatureVerified`; a
satisfied row reports `SignaturePresent` when the declarations block, the
attestation, or a supporting claim/evidence item carries a signature
object, and `Structural` otherwise. `SignatureVerified` exists only for
output-schema stability and is unreachable today.
For a notified body this means an attestation-satisfied row asserts *"the
document says so, in the schema's shape, and nobody in the document
contradicts it"* — not that a signature, a certificate chain, or the
underlying claim was validated. Ingestion of external in-toto / DSSE
attestation bundles (SLSA provenance/VSA and friends) is a later phase with
no surface today; only in-document `declarations` are read.
## BSI TR-03183-2 — quick mapping
`ComplianceLevel::BsiTr03183_2` implements **v2.1.0 (2025-08-20)**: the §4
format gate, the §5.2.1/§5.2.2 required fields, the §5.2.4 additional tier,
§6.1 licence naming, and the §3.1 vulnerability-information prohibition.
SARIF rule prefix: `SBOM-BSI-TR-03183-2-*`. Canonical URL:
[bsi.bund.de/dok/TR-03183-en](https://bsi.bund.de/dok/TR-03183-en).
| §4 (+§7) | CycloneDX ≥ 1.6 or SPDX ≥ 3.0.1 for newly generated/updated SBOMs (Error) | regenerate in an eligible format (v2.0.0 grace ended 2026-02-20) |
| §5.2.1 | Creator of the SBOM with email, or URL if no email (Error / Warning) | `metadata.authors[].email` / SPDX `creator` |
| §5.2.1 | Timestamp of the SBOM data compilation (Error) | `metadata.timestamp` / SPDX `created` |
| §5.2.2 | Component name (Error) and version (Error) | `name` + `version` (filename / RFC 3339 date fallbacks) |
| §5.2.2 | Distribution licence(s) per component (Error) | `licenses[]` with SPDX identifiers |
| §5.2.2 | Hash of the deployable component **as SHA-512** (Error when only other algorithms; Warning when absent, §3.2.1) | SHA-512 hash per component |
| §5.2.2 | Component creator (Warning, presence-level) | `supplier` / `author` per component |
| §5.2.2 | Dependencies (Error) + completeness clearly indicated (Warning) | `dependencies` graph + `compositions[].aggregate` |
| §5.2.4 (add.) | Other unique identifiers — purl/CPE (Warning) | one of `purl` / `cpe` / `swid` / `swhid` per component |
| §6.1 | Licences named by SPDX identifier/expression (Warning) | valid SPDX expressions (text is not a substitute) |
| §3.1 | No vulnerability information inside the SBOM (Warning) | publish advisories separately (e.g. CSAF) |
Not modeled (no rule emitted): filename of the component, and the
executable / archive / structured properties (`bsi:component:*`
CycloneDX taxonomy). The TR mandates **no generation-tool field and no
signature** in any tier.
## CSAF v2.0 (ISO/IEC 20153:2025)
CSAF advisories ingest into `VexEnricher` alongside OpenVEX and
CycloneDX VEX. Format auto-detection: `document.csaf_version` starts
with `2.`. CSAF emit support: `sbom-tools vex export --format csaf`
(see the [CLI cheat sheet](#cli-cheat-sheet)).
| `vulnerabilities[].cve` | `Vulnerability.id` |
| `vulnerabilities[].ids[].text` (fallback) | `Vulnerability.id` (e.g., GHSA) |
| `product_status.known_affected` | `VexState::Affected` |
| `product_status.known_not_affected` | `VexState::NotAffected` |
| `product_status.fixed`, `first_fixed`, `last_affected` | `VexState::Fixed` |
| `product_status.under_investigation` | `VexState::UnderInvestigation` |
| `product_status.recommended` | `VexState::Affected` (with note) |
| `product_tree.full_product_names[].product_identification_helper.purl` | `(vuln_id, purl)` lookup key |
## CLI cheat sheet
```bash
# Multi-standard validate with CRA + BSI + NTIA in one pass
sbom-tools validate sbom.json --standard cra,bsi,ntia
# CRA Phase 2 with product-class calibration via sidecar
sbom-tools validate sbom.json --standard cra --cra-sidecar sbom.cra.yaml
# CRA validation with explicit product class
sbom-tools validate sbom.json --standard cra --cra-product-class important-class-2
# Article 24 steward profile
sbom-tools validate sbom.json --standard oss-steward
# Pin the evaluation clock (Art. 14 deadline, SBOM age, EUCC / attestation
# expiry) so CI runs are reproducible
sbom-tools validate sbom.json --standard cra --as-of 2027-01-01
# SARIF output for CI (with helpUri populated)
sbom-tools validate sbom.json --standard cra -o sarif -O compliance.sarif
# Generate CRA conformity dossier (Annex V DoC + Annex VII technical documentation)
sbom-tools cra-docs sbom.json --output dossier/ --cra-sidecar sbom.cra.yaml
# Curated standards-watch catalogue (prEN, BSI, CSAF, EUCC, …)
sbom-tools cra-standards-watch --format json
# Apply CSAF advisories to enrich SBOM with VEX data
sbom-tools vex apply sbom.json --vex advisory.csaf.json
# Emit the SBOM's VEX state as a CSAF v2.0 advisory
sbom-tools vex export sbom.json --format csaf -O advisory.csaf.json
```
## Sidecar example
```yaml
manufacturerName: "Example Corp"
manufacturerEmail: "legal@example.com"
productName: "Example Product"
productVersion: "1.0.0"
ceMarkingReference: "EU-DoC-2026-001"
supportEndDate: "2030-12-31T00:00:00Z"
productClass: "important-class-1"
conformityAssessmentRoute: "module-a"
riskAssessmentUrl: "https://example.com/risk-assessment.pdf"
riskAssessmentMethodology: "ISO/IEC 27005:2022"
securityContact: "security@example.com"
psirtUrl: "https://example.com/psirt"
coordinatedDisclosurePolicyUrl: "https://example.com/security/cvd-policy"
earlyWarningContact: "ew@example.com"
incidentReportContact: "incidents@example.com"
enisaReportingPlatformId: "EU-MFR-12345"
isOssSteward: false
```
Auto-discovered next to the SBOM at any of:
`<stem>.cra.{json,yaml,yml}`, `<stem>-cra.{json,yaml}`, with multi-extension
stems also tried (`app.cdx.json` → `app.cra.json` works).
## Standards bibliography
| CRA — Regulation (EU) 2024/2847 | https://eur-lex.europa.eu/eli/reg/2024/2847/oj/eng |
| prEN 40000-1-3 (in development) | (CEN-CENELEC JTC 13 — paywalled draft; URLs unstable) |
| BSI TR-03183-2 (v2.1.0) | https://bsi.bund.de/dok/TR-03183-en |
| ENISA SBOM Implementation Guidance | https://www.enisa.europa.eu/publications/sbom-implementation-guidance |
| NIST SP 800-218 SSDF | https://doi.org/10.6028/NIST.SP.800-218 |
| EO 14028 | https://www.federalregister.gov/d/2021-10460 |
| FDA premarket cybersecurity (final, 2026-02-03) | https://www.fda.gov/media/119933/download |
| NTIA SBOM minimum elements | https://www.ntia.gov/report/2021/minimum-elements-software-bill-materials-sbom |
| CSAF v2.0 (ISO/IEC 20153:2025) | https://docs.oasis-open.org/csaf/csaf/v2.0/csaf-v2.0.html |
| OpenVEX | https://github.com/openvex/spec |
| CISA KEV | https://www.cisa.gov/known-exploited-vulnerabilities-catalog |
| OSV.dev | https://osv.dev |
| EUCC (Reg. (EU) 2024/482) | https://eur-lex.europa.eu/eli/reg_impl/2024/482/oj/eng |
| CycloneDX Attestations (CDXA) | https://cyclonedx.org/capabilities/attestations/ |
## Where this map lives in the code
- `rule_meta()` in `src/quality/compliance/registry.rs` (via `Violation::registry_standard_refs()`) —
string → `(StandardKind, id)` mapping. Drives SARIF
`properties.standardIds`.
- `StandardKind::canonical_help_uri()` in `src/quality/compliance/mod.rs` —
`(StandardKind, id)` → URL. Drives SARIF `helpUri` and
`properties.standardHelpUris`.
- `rule_help_uri()` in `src/reports/sarif.rs` — rule-ID prefix → URL
for `runs[].tool.driver.rules[].helpUri`.
- `ComplianceChecker::class_severity()` in `src/quality/compliance/mod.rs` —
P3.2 calibration table.
- `cli::run_cra_docs` in `src/cli/cra_docs.rs` — Annex V DoC + Annex VII tech-doc dossier
generator.
- `AttestationRuleFamily::classify()` in `src/model/attestation.rs` —
`definitions.standards` entry → CRA / SSDF / EO 14028 rule family;
`AttestationDeclarations::supported_requirements()` — the fail-closed
filter behind "when an attestation counts".
- `ComplianceContext::evidence_for()` in `src/quality/compliance/context.rs` —
the query the CRA / EUCC checks call.
- `ComplianceChecker::build_conformity_summary()` and
`check_class_eucc_reference()` in `src/quality/compliance/cra.rs`,
`standard_references_eucc()` / `cdxa_note()` in
`src/quality/compliance/ssdf.rs` — the CRA-side attestation integration
points.