// from the shipped image alone
Know what is in the firmware you ship, and whether it changed.
Upload an image and get the component and version inventory, with every byte accounted for. Works from the shipped image alone.
A hash cannot answer the question
A signature says who published an artifact. A hash says the bytes did not move. Neither says whether the meaning changed, and a rebuilt binary is byte-different every release, so a mismatch is the normal case and carries no information.
In an engagement we compare what the two builds actually do, rather than comparing their bytes. A rebuild of the same code comes back as agreement. A changed check, an added call or a dropped bound comes back as a difference, with the part of the image it sits in named.
What an upload gives you, and what an engagement adds
Two different things, and the difference is stated here rather than discovered after you buy. You can start an upload yourself; an engagement is quoted up front, from what the artifact is, what you are afraid of, and when the answer has to exist.
An upload
The member tree, the coverage account, and the SBOM. Self-serve, from the image alone.
Your release history
Point us at the releases you already have and the SBOM names the components it can match against them. Supply nothing and it reports what the image declares about itself. This is a provisioning step on day one, not a license tier.
An engagement
The diff against a baseline you accepted, and per-binary findings. This is work our engineers do for you, not an upload output, and we say so before rather than after.
Every run ends in one of five answers
Three of the five verdicts say we could not decide, so an artifact we failed to read is never reported to you as a match.
| Verdict | What it means | What you do |
|---|---|---|
| MATCH | Every part we compared behaves the same way, and we read enough of the image for that to be a statement about behaviour rather than about bytes. | Accept on this axis. |
| TAMPER | A specific, named change: this slice, this difference. | Investigate before it goes anywhere. |
| BYTE-IDENTICAL | The bytes are the blessed ones, but a slice carried too little semantic coverage for any claim beyond bit-exactness. Packed firmware lands here. | Treat it as a hash comparison, because that is all it is. |
| ANALYZER-CHANGED | The artifact may be unchanged, but our own analyzer moved, so agreement would be a claim about two different readers. | Re-baseline. Do not re-bless on this. |
| UNLIFTABLE | A slice could not be fully accounted for, so no honest verdict is possible. | Treat it as unverified. Not as clean. |
A bill of materials with a denominator
Which components are in it, at which versions, as CycloneDX 1.6 with a purl on each component whose version the evidence witnessed.
The document carries 2atomic:exec_byte_account_closure printed with the terms it closes over rather than as a bare ratio, so you recompute it. It is exactly 1.0 or the document is not emitted.
Every binary-SBOM tool drops what it could not identify. The difference is whether it tells you.
What each entry carries
- How it was identified, as a count. Discriminating canonical function hashes agreeing with a named indexed build. Not a label; a number you can argue with.
- A version only where the evidence witnesses it. One indexed release makes every match trivially consistent, so no version is emitted. Several pin it.
- The exact advisory list we matched against, named so your own team can repeat the match and get the same answer.
- What we could not open, and why. Each one names the part, how large it is and what stopped us, so padding is reported as padding rather than counted as a finding.
- Agreement too weak to claim stays unattributed, against a published evidence floor, rather than being promoted.
How a run works
Upload in the browser or submit from your build. Same analysis, same bundle, same account of what was not read.
Upload the image you ship
Drag in the file your factory flashes or your updater serves. We unpack it, identify the components and versions we can place, read the code we find, and hand back one sealed bundle. Nothing is needed from the vendors whose code is inside it.
Submit it from CI
The same run, started by 2atomic firmware submit and read back with 2atomic firmware fetch. Add --wait to block until it finishes and --min-coverage to fail a release that explains less of its own bytes than you accept.
The firmware surface, and the state we reach on each part of it
The code was obtained from the artifact and read, so a finding in it is possible.
A byte map or a register map, not a program. Read is the complete answer and nothing further exists to find.
Sealed behind a hardware boundary. Microcode decrypts inside the CPU, so no analyzer crosses it and we say so.
Found, bounded, and its instruction set established. What is left is the way in: for some the vendor publishes none, for others a reader for the container they sit in. Each row names which.
How far we take you toward CRA readiness
Per release, from the image alone, with every finding already filed against the Annex I requirement it answers. Signing the declaration stays yours. Getting you to the point where you can sign it is the work we do beside you, release after release.
You receive
A component bill of materials, per release
In CycloneDX 1.6, the format an auditor already accepts, with each component named so your own records can match it. Read from the image you ship rather than from a build file. Where the evidence stops short of a version, the version is left blank: a parts list that guesses is worse than one that says so.
You receive
An account of every executable byte
What we read, and what we could not, as a number rather than a silence. This is the line an auditor asks for and most reports cannot produce, because it requires knowing the denominator.
You receive
Findings filed against Annex I
Each finding carries the requirement it answers and how it was established -- parsed, executed, or inferred. The control catalogue lives in the engine and is checked by its own tests, so the mapping is code rather than a spreadsheet somebody maintains.
You receive
An advisory join you can re-derive
Each component checked against an advisory list you host yourself, with that list named and the number of matches beside it. Your team can run the same check and get the same answer.
The dates
| Date | What applies |
|---|---|
| 11 Sep 2026 | Article 14 reporting. An actively exploited vulnerability starts a 24-hour early warning and a 72-hour notification to ENISA and your national CSIRT, then a final report 14 days after a corrective or mitigating measure is available (one month after notification, for a severe incident). Binds products already on the market. |
| 11 Dec 2027 | Annex I essential requirements, conformity assessment, CE marking, technical documentation, Annex II user information. Units placed before this are grandfathered unless substantially modified. |
FAQ
When you would actually use this
Three moments, and they are the three people ask about.
Supplier intake
Fingerprint the deliverable on arrival, so every later drop is a diff instead of a fresh act of trust.
Release gate
Ask whether the object about to be published still corresponds to the source that was reviewed, while the answer can still change the outcome.
Incident scope
When a component is reported compromised, compare what you shipped against what you accepted, rather than reasoning from a manifest.