Capabilities
SBOMFlow is the offline-first system of record for connected-device cybersecurity release evidence. This page lists what the product does today, with an honest status for each capability. Nothing here is a roadmap item; planned work is not listed as available.
How to read the status column
| Status | Meaning |
|---|---|
| Default | Runs on every analyze/audit with no flags and no network. |
| Explicit input | Runs offline when you point SBOMFlow at a local file (for example a supplier SBOM or a vulnerability snapshot). |
| Opt-in flag | Off until you pass the documented flag; still offline unless stated. |
| Opt-in network | Contacts a service only under an explicit flag such as --use-osv. Never on by default. |
| Optional extra | Needs an optional Python extra (for example PyYAML or jsonschema). Baseline operation never requires it. |
| External tool | Uses a locally installed third-party tool when present; SBOMFlow works without it and says so. |
| Recognized, not parsed | The input is detected, hashed, and surfaced with a stable warning instead of being interpreted. |
Important
Machine observations never become approvals. Reviewer status defaults tounreviewed; VEX not_affected/fixed and evidence acceptance come only
from human review. See Observed vs reviewed.
Composition and identity
| Capability | Status | Output |
|---|---|---|
Source manifests — requirements.txt, package.json, Cargo.toml, go.mod, Dockerfiles, firmware manifests | Default | components in the evidence pack and SBOMs |
Lockfiles — npm package-lock.json/shrinkwrap, pnpm, Yarn Classic, Cargo, Go modules, Pipenv, Poetry, Composer, Bundler | Default | components with resolved versions, direct/transitive scope, and dependency edges |
Recognized-but-unparsed dependency manifests — Gradle lockfiles, NuGet packages.lock.json, uv.lock, Swift Package.resolved, ESP-IDF dependencies.lock, vcpkg.json, Maven pom.xml, Conan lockfiles, dependency-declaring pyproject.toml | Recognized, not parsed | stable unsupported_lockfile warning naming the exact file |
| Unpinned Python requirements | Default | unpinned_requirements warning counting the declarations that could not be inventoried |
| Package URL identity — canonical purls with namespaces, qualifiers, version epochs, vendor/local suffixes, and container digests preserved | Default | purls in CycloneDX/SPDX and stable component identity |
| Component-identity guard — structurally invalid names/versions from any parser are neutralized and warned, never emitted as inventory | Default | malformed_component_* warnings |
| Dependency graphs — deterministic edges, deduplication, workspace/git/file dependencies, legitimate cycles kept | Default | dependencies in CycloneDX, DEPENDS_ON in SPDX |
Embedded and container builds
| Capability | Status | Output |
|---|---|---|
Yocto image manifests and license.manifest (including under build/tmp/deploy/…) | Default | components with declared licenses and build provenance |
Buildroot legal-info manifests, host/target separation preserved | Default | components with source provenance |
Zephyr west.yml (best-effort; unrecognized shapes warn) | Default | module components |
Container image tarballs and extracted rootfs package databases — dpkg, Alpine apk, SQLite RPM — with observed os-release vendor context | Default | OS-package components with distro/arch qualifiers |
| OCI image layout directories and image indexes | Recognized, not parsed | oci_image_index_not_parsed warning pointing to the opt-in OCI evidence path |
| OCI layout evidence import (manifests, platform variants, attached referrer artifacts) | Opt-in flag | OCI evidence records with verified blob digests |
| Device-tree source overlays | Recognized, not parsed | device_tree_not_parsed warning |
| Further build-evidence importers — CMake File API, linker maps, Zephyr SPDX/Twister, ESP-IDF metadata, MCUboot, update-system manifests (RAUC, SWUpdate, Mender, Uptane) | Explicit input | dedicated evidence artifacts per importer |
Vulnerability and exploitation context
| Capability | Status | Output |
|---|---|---|
| Offline advisory matching against a bundled, clearly-labelled non-real sample feed | Default | findings marked with their provenance |
| Local vulnerability-database snapshots | Explicit input | findings with snapshot provenance and freshness |
| OSV and NVD enrichment | Opt-in network | findings with source URLs and CVSS context |
| CISA KEV and FIRST EPSS | Explicit input or opt-in network | known-exploited flags and exploit-probability scores — inputs for human triage, never verdicts |
| CVSS v3.x base-score computation from vectors | Default | derived severities (never invented) |
| Conservative reachability observations for Python, JavaScript/TypeScript, Go, Rust, C/C++ | Default | reachability.json; not_observed never means safe |
| Reviewer-driven VEX (OpenVEX + CycloneDX VEX) | Opt-in flag | VEX statements; not_affected requires a valid justification or it is downgraded |
| Supplier VEX ingestion (OpenVEX or CSAF) as context | Explicit input | supplier statements kept separate — they never set your status automatically |
| Suggested SSVC priority from the CISA decision table | Opt-in flag | ssvc.json — a suggestion for humans, never a gate or a status |
CRA-oriented evidence
| Capability | Status | Output |
|---|---|---|
| Versioned model of Regulation (EU) 2024/2847 Annex I with evidence mapping | Default | cra-coverage.json; manual-only areas are labelled, not failed |
| Structured manufacturer evidence inputs for still-manual areas | Explicit input | hashed inputs surfaced in coverage — never marked adequate or accepted by the engine |
| Annex VII technical-documentation pack, including an UNSIGNED DRAFT declaration | Opt-in flag | techdoc pack; the draft watermark is validator-enforced |
| Article 14 incident-report drafts (early warning, notification, final) | Opt-in flag | cra-article14-.DRAFT. with submitted: false — SBOMFlow never files, transmits, or contacts a CSIRT/ENISA |
Limitation
SBOMFlow records engineering evidence and gaps. It does not determine legal
conformity, does not classify your product, and does not submit anything to
a regulator. See CRA orientation.
Release workflow
| Capability | Status | Output |
|---|---|---|
Release gate — informational by default, blocking only under explicit --fail-on-* policies, VEX-aware, with the exact reason recorded | Default | release-gate.json and a stable exit-code contract |
| Named, versioned policy profiles | Opt-in flag | recorded policy source and hash in the gate output |
| Release records, release comparison, and drift (components, dependencies, findings, evidence, gates, support periods) | Default / explicit previous output | release-record.json, release-drift.json, local release index |
| Review queue with tamper-evident decisions | Default artifacts, human actions | reviews.json + append-only, hash-chained audit-log.jsonl |
| Multi-role approvals with separation of duties (self-approval rejected), expiry, and revocation | Opt-in commands | approval records tied to exact artifact digests |
| Time-boxed gap/finding waivers | Opt-in commands | waiver records that keep waived items visible |
| Issue exports | Default / opt-in | issues.json, issues.md, CSV and SARIF exports |
| Tracker sync — GitHub Issues, Jira, ServiceNow, Dependency-Track | Opt-in; dry-run by default, network only with --apply and credentials | idempotent sync plans, then deduplicated updates |
| Notifications — Slack, Teams, webhook, email | Opt-in --apply | messages carrying counts and links, never secrets |
| Evidence bundle and auditor handoff | Default with audit; ZIP opt-in | evidence-bundle.json/html/zip — byte-reproducible ZIP |
| Importer/distributor sharing pack (redacted subset) | Opt-in flag | sharing pack with a documented allowlist |
| CI templates for GitHub Actions, GitLab CI, Jenkins | Documented | copy-paste workflows using the stable exit codes |
Provenance and integrity
| Capability | Status | Output |
|---|---|---|
| SHA-256 for every scanned file, and source hashes on every contributing observation | Default | artifact-manifest.json |
| Symlink boundary — paths resolving outside the scan root are refused with a warning | Default | symlink_outside_root warning |
| Resource bounds on untrusted input (size, depth, archive members, decompression) | Default | resource_limit_exceeded warnings instead of unbounded reads |
Deterministic outputs under a fixed --as-of | Default | byte-identical artifacts across repeat runs |
| Structural validation of every output directory, including cross-artifact consistency and audit-chain verification | Default command | sbomflow validate (exit 4 on failure) |
| Official JSON-Schema validation of generated SBOMs | Optional extra (jsonschema) or external CycloneDX CLI | validation notes/errors |
| Local build-attestation (DSSE) verification | Optional extra | provenance verification records |
| Optional local analyzers — syft, diffoscope, cosign, firmware extraction | External tool | adapter evidence with sanitized, bounded execution |
What SBOMFlow deliberately does not do
- It does not claim or certify legal conformity, and it never says "compliant".
- It does not sign, file, transmit, or submit regulatory reports.
- It does not turn machine observations, supplier statements, KEV/EPSS, or reachability into approvals, VEX statuses, or release decisions.
- It does not upload your source, firmware, or evidence anywhere by default — there is no telemetry.
- It does not guess: missing versions, licenses, or origins stay missing and are surfaced, not invented.
- It does not parse every proprietary format; recognized-but-unsupported inputs are hashed and warned so you can route them to review.
Next: what a run produces, or how we test all of this.