What's new
A factual record of recent product improvements. Everything listed is covered by tests and documented, and is in the release its section names. Dates are engineering-verification dates. Where an entry is dated to an earlier month, the figures inside it are the figures as they stood then; the current figures are on Testing and trust.
Note
SBOMFlow versions its artifacts and models; your output records the exact
tool version that produced it. Current release line: 0.5.x.
v0.5.5#
Availability: v0.5.5 is available to approved private testers. It is a certified private v0.5.5 tester build with no known release-blocking defects, subject to the documented restrictions. The build is unsigned and carries no continuous-integration attestation; how to receive it and how to check the bytes you received is on the installation page. What certification established, what it did not, and the real public samples the release was tested against are in the v0.5.5 release record.
The theme of this release: the runtime evidence behind a firmware release becomes part of its record. A trace or crash dump that a team reviewed for a release can now be recorded against that release and the firmware image it ran on, re-checked on every later run, decided on by a named person, and handed on without the original leaving your hands. SBOMFlow reads what a file's header declares about itself; it never decodes events, samples, registers or memory.
Everything below is grouped by what an operator or a reviewer can now do or now see.
Runtime trace and crash evidence in the release record#
The walkthrough is Trace and crash evidence; the set-based workflow is Runtime evidence custody.
- Record a trace or dump against a release and the firmware it ran on.
sbomflow ingest-preserved-artifactwrites one small record per file: its name, size and SHA-256, and what a person stated about it — the release, the scenario, the tool, the firmware image. A statement is recorded as a statement, never as a measurement. Several files from one capture can say they belong together, and a record can say where the original is kept. - The release audit re-checks every recorded file.
sbomflow auditwritespreserved-artifacts.json: each original re-hashed, the firmware image looked up among the files the release scan hashed, the identity the file declares, and its review state. One changed byte suspends a decision made about the file. - A named person decides, and the decision covers those bytes only.
sbomflow reviewrecords the conclusion and its limits against the file's digest, andsbomflow explain --preserved-artifactexplains one record. - See what changed between two releases' runtime evidence.
sbomflow compare-releasesnames each record that was added, removed or re-decided. An earlier decision about identical bytes is shown as context and never applied to the new release. - Hand the evidence on without the originals. The evidence directory, the bundle and the ZIP carry the records and none of the originals; every copy is re-hashed on verification.
sbomflow custodykeeps runtime and test evidence as a set of its own, outside any release run, and exports it for one recipient; it is experimental. - Header identity is read for open formats kept as originals. For each format below, SBOMFlow reads only the header and identity fields the format documents, under a published specification or, where none exists, under open-source code pinned by commit and file digest (the row says
basis: source code). An unknown version or layout is refused by name. - Streaming traces (.psf) written by the TraceRecorder library, as opened in Tracealyzer and other tools, and TraceRecorder snapshots: ring-buffer dumps, stream-port buffers and legacy snapshots. - Alert entries from the open-source DFM library, including the firmware version the device build declares. - Crash dumps: CrashCatcher dumps, Zephyr core dumps, Memfault-format MCU core dumps, minidumps and ELF core files. - Traces and recordings: CTF metadata,perf.data, pcapng captures, Eclipse ThreadX trace buffers, trace-cmdtrace.datfiles and Perfetto traces. - Robotics and drone logs: PX4 ULog flight logs, MCAP recordings and ROS 2 bagmetadata.yaml. - The full list, with each format's basis and the fields read, is under What SBOMFlow reads from your file. - Load images are matched to the ELF they came from. An Intel HEX, S-record or UF2 image kept beside its ELF is compared byte for byte with the ELF's loadable segments at their physical addresses. An image identical to its ELF carries that ELF's GNU build id, labelled derived.
- A declared build id is compared with the release's firmware images. Where a file declares a GNU build id,
build_id_matchsays whether it equals the build id of a firmware image the release declares, by exact, full-length equality. Where a file declares a firmware version, it is set beside the release's own version as context, and is never matched or verified. - A closed format says it is closed. A SEGGER SystemView recording is hashed, recorded and reviewable like any other file, and its row says the format is closed, so nothing inside it is read.
- No gate by default. A trace, a missing decision or a mismatch changes no release gate, VEX status or approval digest. A release can state which evidence it planned to keep, every run compares the records with that plan, and a policy file can opt in to holding the gate on it.
Vulnerability sources you keep locally#
- A local CSAF 2.0 advisory mirror becomes a vulnerability source.
sbomflow vulndb update --source-type csaf-directory --path DIRrecords the accepted advisories as one pinned snapshot, offline, andanalyzeandauditread it with--vulndb-dir DIR. A finding needs a package URL or declared CPE equal to the advisory's; no product name or version range is compared. Keeping the mirror current from its provider is an explicit network opt-in:vulndb update --source csaf-provider --url URL. - One command answers which newly listed known-exploited identifier a stored release records.
sbomflow store exploitation-deltacompares two pinned KEV snapshots and lists, for each newly listed identifier, the stored releases whose frozen evidence records it, with each release's support state. It is offline, and it opens no case and changes no finding, VEX status or gate. - The Linux kernel in a Linux-based device is a matchable component, under the ecosystem the kernel's own CVE authority publishes into OSV.
- Build-applicability evidence records whether a file a kernel CVE names was compiled into the build (
sbomflow build-applicability-evidence). It is context for a human decision, never a VEX status. - Embedded C components get a first advisory route, as candidates and never as findings. CPE candidates are off by default and wait for a reviewer.
- A tool's own vulnerability claims enter the record as that tool's claims.
sbomflow ingest-cyclonedx-vdrreads a CycloneDX VDR/VEX export, andsbomflow ingest-build-cve-reportreads a Yocto or Buildroot build's own CVE report. - Industrial CSAF advisories are read against the devices you declare, as context, where an advisory names a device by vendor, model and firmware range.
SBOMs that keep what they were given#
- Tag-value SPDX is read, so the SBOMs that Zephyr
west spdxand the ESP-IDF SBOM tool write can be imported, and the default scan reads the SPDX 3.0 image SBOM that current Yocto releases write. - Supplier identifiers survive an import and are emitted again: CPEs, SWID tags, SWHIDs and OmniBOR ids.
- A corrected SBOM for the same release keeps its serial number and increments its version, and the run's CycloneDX SBOM states whether its component list is complete.
- An SBOM can name the elements its producer withholds. The declaration is stated in every document a recipient can hold, and the withheld values are omitted from the SBOMs and the VDR. An SBOM author contact can be declared, and a SHA-512 of every scanned file recorded beside its SHA-256.
- More of a firmware tree becomes declared components: git submodules, silicon-vendor MCU project and SDK manifests, the modules Go and Rust binaries were built from (opt-in), and whether linux-firmware's
WHENCElists a shipped firmware blob.
Vulnerability matching on real systems#
- A distribution advisory reaches every binary built from the source package it names, so a single advisory about a source package is no longer missed on the binaries a base image actually installs.
- FIPS and extended-support builds are decided by their own stream, never by the version of the ordinary package they resemble.
- A local or workspace dependency is never matched as the public package of the same name, and a workspace crate carries the version it is built at.
- Every pip requirements file in a tree is read, not only one named
requirements.txt. - OSV's per-ecosystem archives are read offline, as downloaded.
SBOMs compared with each other and with the build#
sbomflow sbom-set compareexplains where two or more SBOMs for the same build agree and differ, fact by fact, without merging, scoring or ranking them, and refuses to compare documents that do not describe the same subject.- A supplier's SBOM is compared with what the build shows where the supplier said what it covers, and supplier VEX is accounted for document by document.
Binaries, images and payloads#
elf-evidencerecords each binary's declared exploit mitigations, andcompare-releasesreports what changed in them. A kernel module records whether it ends with the appended-signature marker.- A release can say which container images and which update payloads carry it, and
compare-releasesshows which images changed.
Handing a release on#
sbomflow export-reqifhands one release to a requirements-management tool as ReqIF 1.2.sbomflow supplier-package emitproduces the package a customer's supplier intake reads.sbomflow case export-advisorygenerates a CSAF 2.0 security advisory from a reviewed case, locally, for you to review and publish. SBOMFlow does not publish, host, sign or upload it.sbomflow store holdandstore release-holdplace and lift a preservation hold on a stored release.
Requirements and support periods#
- A run can be compared with your own requirement list — a customer questionnaire, an internal release policy, a checklist your staff wrote — and a run can declare no requirement regime at all.
- A component's end of support can be declared, or read from lifecycle snapshots, and a component that ends before the release's own support end is a gap row with its source. Fetching a snapshot is an explicit network opt-in (
sbomflow component-support fetch). - Release drift says which way a declared support end date moved.
CLI and operator experience#
- Start from a goal.
sbomflow help goalslists what people come to do, andsbomflow help goal <id>prints the exact steps, what stays human and the network posture. - Every example the CLI prints is executed by the test suite, from the source tree and from an installed wheel.
- Every refusal names a command to run next, and every
--jsonsurface prints one versioned document on stdout, with the same exit code, including on failure.
Known limitations in this release#
- Declared is not verified. A value a file declares about itself is shown as declared. SBOMFlow does not decode a trace or dump, does not check that a declared value is true, and never infers a build from a format that names none.
- A format with no reader row is recorded, not read. Its file is hashed, recorded and reviewable; nothing inside it is read.
- Custody and several new artifacts are experimental and may change without notice; Artifact schemas marks which.
- No compliance claim. The record is engineering evidence of what was reviewed. It says nothing about whether a product is secure or conforms to any regulation.
v0.5.0#
Availability: v0.5.0 was made available to approved private testers as a certified private v0.5.0 tester build with no known release-blocking defects, subject to the documented restrictions. It is superseded by v0.5.5. The build is unsigned and carries no continuous-integration attestation; its identity and digest are in the v0.5.0 release record.
The theme of this release: fewer ways for a release record to look better than it is. Most of it closes the gap between what an artifact said and what actually happened. An empty result and a check that never ran used to look the same on the page; now they read differently, because a reviewer acts differently on each.
Everything below is grouped by what an operator or a reviewer can now do or now see. Where a release brought library work that no command reaches yet, it is named under What did not become reachable rather than dressed up as a feature.
Safer and more honest release gates#
- A gate file that could not be read no longer reads as "no policy enforced". The first-run summary collapsed "unreadable" into "permissive", so a reviewer saw a deliberate decision not to enforce a policy where the truth was a failure to open one. Those are different facts and they now print differently.
- An enforced AI control that could not run blocks, with its own reason code, instead of passing. A control you switched on cannot quietly contribute a pass because its input was missing.
- CI can now fail when a release comparison did not actually happen. Pass
compare-releases --require-both-releasesand a run that had nothing to compare against stops the pipeline, instead of reporting an uncompared run as "no drift". - A comparison with a missing side no longer reports the absent release as change. Comparing against a
--currentthat does not exist used to diff against nothing and present the result as drift.
Stronger verification and refusal semantics#
- The draft-only boundary on Article 14 documents is stricter. A status must now actually be a draft status on every validator that enforces the boundary that keeps every Article 14 output an unsigned draft.
- A run's own SBOM proves something about the tree, not about the run that produced it — and there is now a way to check the second thing.
doctor --analysis-control PATHreads an offline runtime control receipt. - Every surface that shows a drift count now says whether the comparison happened at all. An empty change set used to render identically to a comparison that never ran.
- Coverage is reported with denominators wherever it is reported. A feature with one resolved and one unresolved reference reads as "one resolved, one unresolved", never as "50% traced". This applies to the artifacts that carry it, not to the product as a whole.
Better vulnerability evidence and source provenance#
- "Why were no advisories found for my ecosystem?" now has an answer. A declared advisory match path pointed at an ecosystem the upstream service does not serve, and 26 of 45 served ecosystems carried no coverage statement at all. Coverage per ecosystem is now stated instead of left silent.
- The pinned ENISA Single Reporting Platform field-table extract is current again, so a draft prepared against it matches the field table the platform publishes. SBOMFlow still never files, transmits or signs a report.
Bounded and safer input handling#
- A file you scan no longer decides how much memory SBOMFlow uses. File hashing is now bounded, so scanning a hostile or merely enormous tree stays within budget.
- A scan no longer stalls on a device node. A device node inside the tree no longer stalls a scan; it completes.
- An advertised resource budget is now an enforced one. The AI serving inventory accepted a limits argument and never read it.
- A duplicate key in a JSON-style config is now reported against the line it is actually on.
- Credentials are never sent over a connection that did not negotiate TLS. This is a credential-exposure fix in
notify --apply: if you used it with SMTP credentials on 0.4.x, rotate them.
Better sharing and redaction#
- A shared SBOM no longer commits to the bytes it redacts. Redaction removes the value without leaving a statement that pins what the value was.
- Supplier and originator identities and contact email addresses are now named in the published redaction contract. A reviewer handing a pack to a third party can read that those fields are covered instead of inferring it.
Release memory and verification#
- A handoff document no longer carries your filesystem layout. The release dashboard rendered to the same absolute
--outputfrom two different working directories produced byte-different documents, each embedding the caller's directory names. It is now deterministic, and the path leak is gone with it. - An evidence pack built on one operating system now matches one built on another. Sixteen recorded relative paths carried the host path separator.
- A consumer-visible SBOM correction. SPDX 2.3
primaryPackagePurposefor an operating-system package was not a legal enum value: up to and including v0.4.0 SBOMFlow wrote a non-standardOPERATING-SYSTEM, and it now writesOPERATING_SYSTEM. If you stored an SPDX SBOM from 0.4.0, see the note in Outputs. - Every published figure is now policed by its own drift tolerance, so a number on a public page cannot fall silently behind the thing it describes.
AI and model evidence you can reach#
Every item here names the command or flag that reaches it. Nothing in SBOMFlow runs, evaluates or scores a model, and nothing observes runtime behaviour.
- Hand the run your own declaration of the AI in your release, and see where it disagrees with what was found.
analyze --ai-manifest <file>andaudit --ai-manifest <file>. The declaration never overwrites the observation, a conflict is surfaced and never resolved automatically, and a run without the flag says plainly that nothing was compared. Reachable is not supplied: the flag existing does not mean anyone supplied a manifest. - See the agents, tools, services and MCP servers in your release tree without declaring them. An ordinary
sbomflow analyzereads framework and deployment configuration, dependency files, imports and environment-variable names; secret values are never recorded, and each detector publishes what it cannot see beside what it can. - Emit standards-based AI BOMs alongside the software SBOM, linked rather than copied:
--emit-mlbom(CycloneDX 1.6 ML-BOM) and--emit-aibom(SPDX 3.0.1 AI profile), both onanalyzeandaudit, both opt-in. The software SBOM remains CycloneDX 1.6 and SPDX 2.3. - Review AI entities and gate on them, opt-in and off by default.
sbomflow explain --ai-entitysurfaces them for review, and six configuration keys turn individual AI controls into enforced ones. - Read a machine-readable map from published AI documentation duties onto the evidence your run actually produced.
ai-evidence-map.jsonis written on everyanalyzeandauditrun, with one binding source and four voluntary guidance sources, each carrying its official identifier, URL, version or effective date, exact article reference and the digest of the pinned extract, and each expectation naming who supplies it. This artifact is experimental and may change without notice. - See which SBOM formats and minimum versions the BSI TR-03183-2 guideline accepts, in the report itself.
bsi-tr03183-2-presence.jsonrecords field presence. It is not a conformance assessment. - Two AI rows caught up with the code. Agent, tool and MCP dependency discovery was published as planned while it already shipped. The correction ran from under-claim to accurate.
CLI and operator experience#
- Know exactly what
quickstartis about to touch before it writes anything. The pre-write disclosure is now readable output rather than a wall of text, a home-rooted path prints as~/my-productinstead of your account-qualified home path (a path outside your home still prints verbatim, on purpose), andquickstart --jsonprints the same disclosure as one versioned document and exits without writing, auditing or asking. - A next-actions worklist that is current, sourced, and whose commands actually run.
sbomflow next-actions. - Terminal output wraps to the terminal it is printed on — including the pre-run disclosure, which used to be the least readable text in the product. Nothing was shortened to achieve it, and redirected output is unchanged.
Documentation and trust#
- Five explanatory diagrams, each generated from repository truth rather than drawn by hand — the network boundary diagram on Security & privacy is derived from the boundary itself.
- The two longest reference pages became navigable, and the compatibility matrix now publishes each row's trigger and result rather than the lane alone.
- The public job contracts are published as an executable registry. Each of the eight jobs is bound to six proofs that must all be recorded on one candidate build. No job carries the complete set, so no job is described as available. All of the recorded evidence is synthetic or open-source; none of it is real-customer validation.
Packaging and clean-machine installation#
- A clean-machine install is proven with the index switched off. The wheel installs into a fresh virtual environment with
--no-index --no-depsand the installed CLI runs the demo, so0required runtime dependencies is a behaviour rather than an assertion. - Three independent builds of the release tree produced a byte-identical wheel, and every one of the wheel's 385 entries was inspected. The scope is one machine, one interpreter, one operating system — same-environment reproducibility, not a cross-platform claim.
- The release identity a public page may state is generated from one source, so tag, commit, tree, wheel name and wheel digest cannot drift apart between pages. They are listed on the installation page.
Known limitations in this release#
- The build is unsigned and has no continuous-integration attestation. A matching SHA-256 is an integrity comparison against the bytes the build produced. It is not a signature and does not establish who built them.
- "No known release-blocking defects" is not "error-free", and it is not a statement about defects nobody found.
- Native Windows is unproven. The native-Windows check runs and has never passed. Run SBOMFlow on Windows through WSL. macOS on Intel is unverified — no run has been performed, so nothing is known either way.
- Optional trust layers are not claimed where their extra was absent. A check that could not run because
cryptographyorjsonschemawas not installed reports that it was skipped; it never reports a pass. - Most artifact schemas are experimental. Twenty-four of the twenty-nine documented artifacts are marked experimental in Artifact schemas and may change without notice. Nothing here claims schema stability.
- Some warning codes are registered but not currently emitted. Twenty-seven entries in the warning catalogue say so on their own line: the code exists, the behaviour behind it does not ship.
- Three recovery playbooks are deferred — the two covering signature verification, because that surface is not yet published, and the broken post-market projection playbook, which ships when it stabilises. See Recovery playbooks.
What did not become reachable in v0.5.0#
Five headline pieces of v0.5.0 are library foundations. Their code exists, they have tests, and their warning codes are in the published catalogue — and no command, flag or configuration key reaches any of them. They are listed here so a reader does not infer availability from a catalogue entry:
- SBOM concordance
- AI feature traceability
- upstream AI lifecycle events
- the framework-adapter contract
- training-run receipts
The framework-adapter matrix is the one nuance worth keeping: it is a document generated from the same registry the adapters use, so you can read it, and the page says in its own words that the registry is not wired into a run and that the states on it are not emitted by any command. One adapter is defined — never "framework adapters" in the plural sense of a shipped capability.
AI runtime assurance is not what SBOMFlow does and is not finished; it remains design-partner gated and incomplete. Dataset evidence, prompt evidence and redacted AI evidence sharing are planned and nothing is built. SBOMFlow never certifies an AI system, never decides whether one is safe or compliant, and gives no conformity, certification, safety or security verdict about your product.
August 2026#
The pre-run disclosure stops printing your account name, and now has a JSON form#
- A home-rooted path prints as
~/my-product. The blockquickstartprints before it writes anything named every path in full, so the first thing a new operator saw — and pasted into a screenshot, a shared terminal or a CI log — carried the operator's account-qualified home path three times, and twice more under--ci. Every path the disclosure renders now collapses the home directory to~. - Redacted, and still the thing you were asked to confirm. This block exists so you can recognise the directory about to be scanned before anything is written to it; a hash or an elision would have removed the account name and the point of the surface together.
~/my-productis recognisable and expands back to the exact path. - A path outside your home directory is printed verbatim, on purpose. Redaction here hides an account name; it is not truncation. "We are about to write somewhere you did not expect" is precisely what this block must not hide, so an out-of-home location keeps every character.
sbomflow quickstart --jsonprints the same disclosure as one versioned JSON document and exits without writing, auditing or asking — the pre-write surface, now readable by a script. Pinschema_version(sbomflow-quickstart-preflight-v1, orsbomflow-quickstart-ci-preflight-v1under--ci, which is a different document). It is the same document the terminal renders rather than a summary built beside it, so the two cannot drift: the file count still says whether it is exact, a labelled lower bound from a walk that hit its entry budget, or not established at all, and an output directory that could not be listed still reports asunreadableand never asempty.
Terminal output wraps to your terminal, including the pre-run disclosure#
- The block that says what a run is about to do is now readable. Before
quickstartwrites anything it discloses the scan root, the output directory, the config it will create and the fact that the run is offline. That block was printed unwrapped at up to 243 characters — the most safety-relevant text in the product was the least readable text in it, wrapping three times on a standard terminal.quickstart,analyze,auditandreviewnow lay their output out to the width of the terminal they are printed on. - One rule, one place.
sbomflow help <command>already honouredCOLUMNS; the run did not, and a third surface wrapped to a fixed width it could not see past. All of them now derive the same width, clamped so a very narrow terminal does not produce one word per line and a very wide one does not produce full-width prose. - Nothing was shortened or dropped to make the text narrower. Wrapping changes where lines break and nothing else: no warning, refusal, disclosure sentence, provenance line or count lost a word, and a test asserts that by re-joining the wrapped output and comparing it character for character against the text it started from.
- Redirected output is unchanged. With no terminal to ask — piping to a file, or in CI — the layout is exactly what it has always been. Generated files (
cli-reference.md, the man page, the shell completions) pin their own width and never followCOLUMNS, so they still regenerate identically everywhere.
The compatibility matrix now publishes the trigger and the result, not just the lane#
- Each row says which events actually run it. Five CI lanes are skipped on a push to
main, so a green run there is evidence about two Ubuntu interpreter lanes and nothing else. The compatibility matrix previously said the lanes ran "on every push and pull request"; that was wrong for four of the six published combinations, and each row now states its own trigger. A drift test derives the trigger from the workflow file, so the page cannot quietly round it up again. - The native-Windows lane is reported as what it is: red. It runs on every pull request and every nightly and has never passed. The page used to say the lane stopped before finishing and that most of the suite had never been observed running on Windows. That was not true: the suite completes there and fails. Tested-and-red is a worse status than we had published for ourselves, and it is the accurate one. The recommendation is unchanged: run SBOMFlow on Windows through WSL.
- Two claims are withdrawn rather than reworded. macOS-on-Intel is named as unverified instead of "expected to work", and the filesystem-support page no longer says CI execution is unavailable — the Ubuntu and macOS lanes run and have completed green. Where a platform is unverified, the page now names it.
Every release now records what intelligence shipped in it (experimental)#
ai-evidence.jsonis written on everyanalyzeandauditrun and listed inSTART-HERE.md. It inventories the AI model artifacts in your release tree against the same release identity as the rest of the pack, with each artifact's path, size, SHA-256 and — the part that matters — how strongly it was identified: a documented magic number (GGUF, TFLite), a documented structural invariant (SafeTensors; ONNX, which defines no file magic at all), or the filename alone, which is recorded as such so you can see when a claim rests on a name an attacker controls.- Nothing is loaded, deserialised, or executed. The formats most widely used to ship weights are designed to reconstruct arbitrary objects, so "load it and read the metadata" is code execution with extra steps. Those formats are recognised and refused: recorded and hashed so their presence is visible evidence, deliberately never opened. Signatures are checked as well as extensions, so a pickle wearing a
.onnxname is caught by its bytes and the disagreement is raised rather than swallowed. - A truncated inventory says so. The tree walk is bounded on entry count and directory depth and does not follow symlinks out of the scan root; if a budget stops or prunes it, the inventory is reported as partial and names the budget that fired. One over-deep directory never erases the inventory of its siblings.
- An empty result is stated honestly. A product with no AI in it gets a record saying the scan looked and recognised nothing — which is never the same claim as "this product contains no AI". Unrecognised formats, models fetched at runtime, and models behind an external service are outside what any filesystem walk can see.
- Honest scope: this is an inventory for a human, with no score, no verdict, and no safety or conformity claim. It assesses no model's behaviour or quality and observes nothing at runtime. The declared-manifest and agent-authority models now reach a run through
--ai-manifest; a run without the flag stays observed-only and recordsmanifest_supplied: false, and a declared agent is still never merged with a discovered one, because static discovery cannot decide an agent's identity and merging on a guess would fold staging into production — see capabilities for the per-row status and known limitations for the edges.
CRA Article 14 drafts now show the clock, on the right anchors#
- Each stage draft carries a deadline window block evaluated as plain elapsed time against instants you record. Four windows are shown because Article 14 defines four — started by three different events. Neither final-report window runs from awareness, so each stays unknown by name until you record its own anchor rather than being measured from some other timestamp. "We could not work it out" and "there is still time" are different states with different words.
- It shows the clock and the fields; it never decides that anything is reportable, and SBOMFlow still never files, transmits, signs, or submits anything, and contacts no authority or reporting platform.
July 2026#
The filesystem & concurrency contract is now published — and tested#
- Filesystem & concurrency support states exactly which filesystem and cross-process guarantees SBOMFlow makes, where each is verified, and what is explicitly out of contract (network mounts, cloud-synced directories, FAT/exFAT media) or pending external validation (native Windows). Every tested row is pinned to an executable check in the offline suite — killed writers, SIGKILLed lock holders, injected fsync failures, real case-insensitive-volume behaviour — so the page states what is proven, not what is hoped. Process crash, OS crash, and power loss are three explicitly distinct claims: the first is tested, the last is deliberately never made.
Operator recovery playbooks, tested end-to-end#
- Recovery playbooks documents one diagnose → recover path per operational failure — interrupted decision transactions, corrupt journals, audit-chain mismatches, expired waivers, stale advisory snapshots, schema migrations, evidence gaps, and unmet approval quorums. Every tested playbook is exercised end-to-end by the offline suite: the failure state is really created, the documented commands are really run, and the documented recovery is really verified, so the page cannot drift from the product.
Advisory matching you can trust across ecosystems#
- Maven coordinates now match across separator conventions. Real-world advisory data names Maven packages
group:artifact; component identities recorded from build files usegroup/artifact. These are now matched consistently (with guards so different coordinates can never be bridged), closing a silent false-negative class for Maven and Gradle projects. No action needed — re-running an audit picks this up. - Business-scale advisory validation. The synthetic manufacturer laboratory now drives a full ~4,900-component estate through offline advisory matching with positive and negative controls, so more findings can never read as a better score. See testing & trust.
- Remaining limitation: Maven-native version-range ordering is not yet implemented; such ranges surface as
unknownfor human verification instead of deciding silently. See known limitations.
Large monorepo inputs now parse#
- Recognized structured inputs (lockfiles, manifests, SBOM files) parse up to 50 MB — previously anything over the general 5 MB text-scan limit was skipped. A measured example: a 22.4 MB
package-lock.jsonwith ~50,000 components scans in about 11 seconds using roughly 760 MB peak memory (Apple Silicon; results vary with hardware and input shape). - Nothing over a cap disappears silently. Inputs beyond the applicable limit are still hashed and produce a documented
resource_limit_exceededwarning with a concrete remedy (split the input, or supply a generated SBOM via--import-sbom).
Evidence that travels between machines#
- Operator-supplied evidence paths are recorded relative to the scan root whenever the file sits under it, so a recorded location no longer depends on where the checkout happens to live — and internal reviewer bundles carry no local usernames. A file kept outside the scanned tree has no root-relative form, so it is recorded by leaf name alone: the filename survives, and the directory it came from is not part of the record. (This form was
external/<filename>in v0.5.0; the first component is now tooutside-scan-root/so it can no longer be read as a real in-product directory calledexternal.) External sharing packs were already redacted. No action needed; the first re-run rewrites the recorded forms. - Two checkouts of the same tree produce byte-identical evidence packs, SBOMs, and release records when the config declares its evidence with paths relative to
sbomflow.yaml. Declare them as absolute paths and the config file itself differs between the two machines; because it sits inside the scanned tree it is hashed like every other file, so its recorded hash differs even though its recorded path does not. Relative declarations keep a run reproducible across machines. - The same rule covers config-declared evidence, not only the paths passed as command-line options. Annex I evidence inputs, Annex VII technical-documentation inputs, manual reachability evidence, Article 13(6) due-diligence records and a standalone release-gate policy file all record their locations the same way — including where a requirement assessment republishes a supplied file as a manufacturer evidence reference in
cra-coverage.json, and where a scan warning names a vulnerability-database store in its message. Recorded strings only: every file is still opened and hashed through its resolved path.
Hardened scanning boundaries#
- Symlink scan boundary — a symlink that resolves outside the scan root is refused with a
symlink_outside_rootwarning, so a planted link can never pull foreign files into evidence. Limitation: links resolving inside the root are followed by design. - Bounded untrusted input — container-image members, deep YAML nesting, and oversized structures hit explicit budgets and surface
resource_limit_exceededwarnings instead of unbounded reads. - Safer reports — CSV exports neutralize spreadsheet-formula injection; HTML reports escape scanned content; CLI interruptions (Ctrl-C, closed pipes) exit with conventional codes instead of tracebacks. See exit codes.
More honest component identity#
- Cargo inline-table dependencies now yield the declared version — a dependency written as a table with features can no longer leak its raw text into your SBOM, and version-less git/path dependencies are never invented.
- Container references parse name, tag, and digest precisely: a digest-pinned image keeps its immutable digest as identity (no fabricated
latest), registry ports are never read as tags, and digests survive into emitted purls as qualifiers. - A component-identity guard now backstops every parser: structurally invalid names or versions become warnings instead of inventory. Legitimate epochs, vendor suffixes, prereleases, ranges, and descriptive names pass through untouched. Limitation: this is defense-in-depth against structural garbage, not proof a parser's semantics are correct — parser tests do that.
Fewer silent gaps#
- Build outputs inside
build/directories — Yocto image manifests,license.manifest, and generated SBOMs are now scanned where real build systems put them, instead of being skipped with the build tree. - Recognized-but-unparsed formats warn — Gradle/NuGet/uv/Swift/ESP-IDF/ vcpkg/Maven/Conan manifests, OCI image indexes, device-tree overlays, and unpinned Python requirements now produce stable, actionable warnings instead of disappearing into the artifact list. Every warning code is documented (the page is generated from the catalog).
- CycloneDX naming conventions (
bom.json,.cdx.json,.cdx.xml) are recognized as existing-SBOM evidence alongside SPDX.
Deeper verification behind the release#
- The offline suite grew to 1,300 tests as of this entry, including new determinism, boundary, injection, and identity regressions. That was the count at the time; the current figure is on Testing and trust, and it is much larger.
- A ten-archetype synthetic manufacturer corpus now stress-tests the full workflow, with an acceptance contract and a per-fact semantic evaluation that fail on silent omissions, false merges, false positives, or overclaims. Limitation: synthetic testing is not real-customer validation — see Testing and trust.
Earlier in 2026#
- Release history and drift — every run emits a release record; comparing releases yields component, dependency, finding, evidence, gate, and support-period drift, with issue lifecycle states (
new,persistent,resolved,regressed). - Reviewer workflow and approvals — a review queue with tamper-evident, hash-chained decisions; multi-role approvals with separation of duties, expiry, and revocation; time-boxed waivers that keep waived items visible.
- CRA-oriented evidence — versioned Annex I coverage mapping, Annex VII technical-documentation packs with validator-enforced UNSIGNED DRAFT declarations, and Article 14 draft workspaces that are never filed or transmitted.
- Exploitation context — CISA KEV, FIRST EPSS, conservative reachability, and suggested SSVC priorities as reviewable inputs; VEX-aware gating that a reviewer decision — and only a reviewer decision — can suppress.
- Evidence bundles and sharing — deterministic reviewer bundles with byte-reproducible ZIPs, and redacted sharing packs for importers and distributors.
- Stable operator contract — documented exit codes, cataloged error codes with fixes and docs links, and
doctor/init/validate-config/quickstartfor first-run setup.
For the complete capability list, see Capabilities.