EU Cyber Resilience Act
The CRA asks for evidence. A scanner can produce some of it.
The Cyber Resilience Act puts continuing obligations on the people who place software on the EU market: know what is in the product, handle vulnerabilities on a clock, test and review regularly, and keep documentation that shows it. Some of that is an organisational process no tool can run for you. Some of it is an artifact, and artifacts can be generated. This page separates the two, and says plainly which side each item falls on.
- SBOM in CycloneDX and SPDX
- OpenVEX exploitability document
- Per-control evidence pack
- Built offline, on your machine
01 / What the CRA asks for
The requirements, in plain language
Written for planning rather than for filing. Nine areas, each summarised in a sentence, with the binding text named under the table.
This page is not legal advice, and nothing on it is a determination about your product. Which obligations apply to you, and by when, depends on what you make and on your role in the supply chain. Those are decisions to make against the official text of the regulation, with people qualified to make them.
| The area | What it asks for |
|---|---|
| Ship without known exploitable vulnerabilities | A product with digital elements is expected to reach the market in a secure state: a secure default configuration, a limited attack surface, and no known exploitable vulnerability left in it. |
| Know and document what is in the product | The manufacturer identifies and documents the components it contains, including a bill of materials in a commonly used, machine-readable format covering at the very least the top-level dependencies. |
| Handle vulnerabilities without undue delay | Find them, fix them, and distribute the fix, for the support period declared for the product. This is a continuing obligation rather than a one-off check at release. |
| Test and review, regularly | Security testing and review of the product happen on a cadence and leave something behind that can be shown, rather than being asserted after the fact. |
| Run coordinated vulnerability disclosure | A policy for receiving reports from outside, and public information about vulnerabilities once they are fixed, including where to get the fix. |
| Distribute updates securely | Security updates reach users through a mechanism that protects their integrity, and they are disseminated without delay. |
| Report on a clock | Actively exploited vulnerabilities and severe incidents are reported to the authorities the regulation names, within the deadlines it sets. This is a process with recipients, not a document. |
| Keep technical documentation | A file that shows how the requirements were met, kept current for as long as the product is on the market. |
| Assess conformity, scaled by product class | The route to conformity depends on what the product is. Some classes can be self-assessed; others involve a notified body. Which one applies is a determination about your product, not about your code. |
On timing, the dates published with the regulation are that it entered into force on 10 December 2024, that the reporting duties apply from 11 September 2026, and that the regulation applies in general from 11 December 2027. Confirm all three against the official text before you plan around them: this page tracks what a scanner produces, not the legislative calendar.
02 / What Vulkro produces
Five artifacts, all written on your own machine
Each of these is a file a reviewer can open, diff and archive. None of them is a status you are asked to take on trust, and none of them is uploaded anywhere to be produced.
- A component inventory
- A CycloneDX or SPDX SBOM built from the versions your lockfiles resolved to rather than the ranges your manifests declare, with a purl per component and the licence where one could be resolved. A CBOM is available separately for cryptographic assets found in your own code.
- An exploitability statement
- An OpenVEX or CycloneDX VEX document giving each dependency advisory a status of affected, not_affected or under_investigation. A not_affected statement is emitted only where reachability analysis found no call path into the vulnerable code, and the document carries that reason. Where no claim can be made, the status is under_investigation rather than a convenient not_affected.
- Vulnerability findings with their evidence
- Each finding cites a file and a line, and carries the taint trace or the call chain it was derived from. The same pass matches your dependencies against a CVE bundle that lives on your disk, so the component list and the advisory list come out of one run rather than two tools that disagree.
- A per-control evidence pack
- vulkro compliance-pack maps findings onto the control identifiers of a chosen framework and writes one file per control, each citing the findings and endpoints it was built from. vulkro cra-bundle runs the same pack and staples it into one zip with the SBOM pair, the VEX document and a self-contained readiness one-pager.
- A repeatable test, with a diff
- The scan is deterministic: the same tree, the same binary and the same settings produce the same findings in the same order. That is what makes two scans comparable, so a regular review leaves behind an artifact and a difference rather than a recollection.
- cra-readiness.zip/built on this machine
- index.htmlreadiness one-pager
- compliance/soc2-full, 61 controls
- manifest.jsonframework, scan id, control summary
- summary.mdevery control with its status
- findings.csvfinding to control mapping, flat
- soc2-full.htmlper-control evidence table
- controls/one file per control
- CC6.1.jsonPass
- CC6.6.jsonPartial, 2 findings
- CC7.2.jsonFail, 1 finding
- CC8.1.jsonPass
- P4.1.jsonPass
- ...56 more control files
- README.mdwhat each file is, and what it is not
- sbom/
- cyclonedx.jsonCycloneDX 1.6
- spdx.jsonSPDX 2.3
- vex/
- openvex.jsonOpenVEX 0.2.0, per CVE
$ vulkro compliance-pack . --framework soc2-full --output ./compliance/
vulkro cra-bundle runs the same pack and writes it into one zip with the SBOM and VEX documents beside it. Every file is generated locally: nothing is uploaded, and each control file cites the findings and endpoints it was built from.
The SBOM and VEX formats, the spec versions they target, and the reachability analysis behind a not_affected statement are covered on the SBOM and VEX page. The frameworks the evidence pack can map onto, and what an assessor sees when they open one, are on the regulated-environments page.
03 / What it does not do
It produces evidence. It does not produce compliance.
This is the section that matters most on a page like this. A tool that lets a reader believe it closed an obligation it never touched has done them real harm.
The useful frame is narrow. A static scanner reads the code and the artifacts in your repository and writes documents about them. That covers the inventory, the exploitability assessment, and a repeatable review that leaves something behind. It does not cover the parts of the regulation that are about what your organisation does, who it tells, and when.
| What it does not do | What that means | Why |
|---|---|---|
| It does not make you compliant | Producing the bundle does not make a product conformant with anything. It produces evidence that a person still has to assess. | Conformity assessment is a procedure the regulation defines, carried out by the manufacturer and, for some product classes, with a notified body. The bundle says so on its own front page: readiness evidence, not a conformance attestation. |
| It does not classify your product | Nothing in the output decides which requirements apply to what you make. | The obligations scale with the product class and with your role in the supply chain. That determination is made against the regulation with people qualified to make it, not against a scan. |
| It does not file anything | No report is submitted on your behalf, and no deadline is started, tracked or reminded about. | Reporting is a process with named recipients and a clock. A scan can tell you a component is affected; it cannot tell you that exploitation is happening in the field, which is the trigger the duty turns on. |
| It does not cover the organisational requirements | A disclosure policy, a declared support period, and a secure update channel are not scanner output. | They are things an organisation decides, operates and documents. The evidence pack sits beside them in a technical file rather than standing in for them. |
| The inventory is only as complete as what is parsed | A dependency declared in a manifest format the scanner does not read is absent from the SBOM, and a language with no parser is counted and skipped rather than analysed. | Absence is reported as unread rather than as clean, which is the only honest way to hand an incomplete inventory to a reviewer. The dependency graph also asserts one edge, from the root application to every resolved component, and leaves the tree between components unstated rather than inventing it. |
| It does not read anything at runtime | Nothing is executed. Deployment posture, live infrastructure and behaviour under load are outside what the scan sees. | The scan reads the tree on your disk and the artifacts in it. A defect that only appears while the process runs is out of scope, and so is anything that depends on production data. |
| A reachable verdict is not a demonstration | Reachable means a call path exists in the code. It is not evidence that anyone can trigger it as you have things deployed. | Network position, feature flags and whatever sits in front of the route are not visible to a static read. The VEX document labels the call chain as static reachability evidence for exactly this reason. |
The same boundary is printed inside the artifact, not only on this page. Anyone who opens the bundle reads it before they read a single finding, which is deliberate: the accuracy page takes the same line about what the scan measures and what it does not.
04 / Where it runs
Air-gapped, and on the machine that holds the code
Teams with a regulatory reason to generate this evidence are usually the teams least able to upload the code it is generated from.
The whole pipeline is local. Source is read from disk, the call graph and taint analysis are built in memory, findings are written to a local database, and every document on this page is rendered from that run. Advisory matching reads a CVE bundle that lives on your disk, distributed as a checksummed archive you can move into a closed network yourself, so a machine with no route out still matches dependencies against current advisories.
One line leaves the machine in a normal installation, and it carries an entitlement check rather than anything about your code. VULKRO_OFFLINE=1 closes it, and an air-gapped deployment runs on a signed, machine-bound licence file instead of an online sign-in.
Everything the scan needs stays on your machine: the code it reads, the map it builds of how your product fits together, the findings it writes, and the optional local model it can consult without leaving the machine. One line leaves.
- Stays on this machine
- source code, call graph + taint, findings, account layer, and the local model on 127.0.0.1
- One crossing
- A signed entitlement check and a usage counter, on a debounced cadence.
- Never crosses
- source code, file paths, file names, finding contents, project names, the hardware fingerprint
Deployment detail, bundle distribution and the licence-file path are on the enterprise page. The framework mappings, the evidence pack and the audit workflow around them are on the regulated-environments page.