Supported inputs
This matrix is generated from the recognized-input catalog, so it is the exact truth of what a default sbomflow analyze/audit run reads — not a hand-written promise. "Supported" means corpus-tested: the parser has a regression corpus, nothing more. A recognized-but-unparsed input is detected, hashed into the artifact manifest, and surfaced with a stable warning — it is never silently ignored. Anything not listed here is not recognized as inventory in the default scan.
Parsed by default (75 tested)#
| Input | Family | Kind | Notes | ||
|---|---|---|---|---|---|
*.spdx.index.json (glob) | yocto | Build evidence | The create-spdx document index; used to detect a partial doc set. | ||
*.spdx.json (glob) | yocto | Build evidence | Parsed for components only when the document carries the Yocto create-spdx creator marker (the SPDX 2.x document set). A Yocto create-spdx-3.0 image SBOM (Yocto 5.1 and later; the only SBOM 6.0 writes) is read too, selected by its structure and never by its name or directory: an SPDX 3.0.1 JSON-LD graph holding an OpenEmbedded build and an assembled software_Sbom. Its recipes become components keyed pkg:yocto/<layer>/<BPN>@<PV>, the binary packages in the image are recorded as occurrences of them, the CPEs the build states are recorded as declared by the build, and -native recipes are marked build-host-only; the build's own VEX statements are counted and never interpreted, and an SPDX 3 version other than 3.0.1 is refused by name. Every other SPDX document is hashed and imported via --import-sbom. The optional first-party meta-sbomflow layer collects the document set without promoting build-host recipes into shipped components. | ||
modules.dep | linux-kernel | Installed state | A root filesystem's kernel module index — only as lib/modules/<release>/modules.dep (also under usr/; the bare name claims nothing). depmod writes it into the directory named for the kernel release the modules were built for, so the PATH states which kernel the image ships and the file's content is not read for identity. It becomes a pkg:generic/linux-kernel@<upstream version> component (purl-spec has no kernel type; none is minted) with the release kept as raw_version and the kernel_release qualifier, and it is merged with a Yocto kernel package (kernel-<release>) and a Buildroot legal-info linux row describing the same kernel into ONE component; two release directories are two components. It is matched against the kernel CNA's OSV records (ecosystem Linux, package Kernel) under the validated linux-kernel ordering; a vendor, BSP, real-time or distribution suffix matches on the upstream base at match_confidence low (kernel_version_vendor_suffix), and a release with no upstream version at its front is inventoried unversioned and never matched (kernel_version_unresolved). No build applicability is read, so kernel matching over-reports by design. | ||
opkg/status | opkg | Installed state | The opkg/ipkg installed-package database of OpenWrt (through the 24.10 series) and Yocto ipk images — only under usr/lib/opkg/status, var/lib/opkg/status or usr/lib/ipkg/status (the bare name status claims nothing, and var/lib/dpkg/status stays the container parser's dpkg database). Installed stanzas become components with the stated exact version and architecture, and Depends yields dependency edges. A stanza whose Status names any other state (not-installed, half-installed, config-files) is a complete record of absence and is skipped silently; a stanza whose Status is absent or is not the three fields <want> <flag> <state> is skipped AND warned about, because a truncated database that told us nothing must not read the same as one that told us the package is not there. Neither is ever invented into a component. A stanza whose STRUCTURE is ambiguous is warned about too, and never repaired: a field stated twice with different values (last-wins discards the earlier one — where the field is Status, the line order alone decided whether that package is listed as shipping), and a stanza stating Package: more than once, which is the signature of a lost blank-line separator left by an interrupted write. Such a stanza is NOT split: where the separator belonged is not readable and guessing it would invent inventory, so a package the file names is absent from the component list, and the surviving record's Auto-Installed/Depends marks are kept verbatim but not attributed to it. purl-spec defines NO opkg/openwrt type and OSV serves NO OpenWrt ecosystem (both verified 2026-07-17), so components are honest pkg:generic/<name>@<version> with match_scope: none — never pkg:deb, and never a guessed distro. OpenWrt 25.12+ switched to apk; its installed database (lib/apk/db/installed, an FDB text file — verified against apk-tools source) is read by the existing container apk parser. | ||
status | vcpkg | Installed state | only under vcpkg_installed/**/vcpkg/status. Same Status discipline as the opkg row: a state naming absence is skipped silently, an absent or non-three-field Status is skipped AND warned about. vcpkg's grammar is <want> ok <state> — vcpkg-tool writes that middle field as a string literal and its own reader requires it — so a middle field that is not ok is a document vcpkg cannot produce and is reported as unreadable rather than read as a record of absence. hold is a want value (the FIRST field), so a held but installed package is hold ok installed and ships. The opkg row is deliberately more permissive in that position because libopkg writes ok/reinstreq/hold/replace/noprune/prefer/obsolete/user there, comma-separated when combined: each parser follows its own writer. Structural ambiguity is reported and never repaired, on the same terms as the opkg row: a field stated twice with different values (last-wins discards the earlier one), and a stanza stating Package: more than once, which is the signature of a lost blank-line separator left by an interrupted write. Such a stanza is NOT split — guessing where the separator belonged would invent inventory — so a port the file names is absent from the component list, and the surviving record's Port-Version/Depends marks are kept verbatim but not attributed to it. Port-Version matters most there because it is a purl QUALIFIER: pinning the vanished port's revision onto the survivor would mint an identity the file never claimed for it. | ||
bun.lock | bun | Lockfile | Bun's text lockfile (JSONC, Bun >= 1.2), read with a deterministic comment/trailing-comma strip into the same bounded JSON loader as every other lockfile. Registry resolutions become pkg:npm/<name>@<version> (immediately OSV-matchable) with the stated SRI integrity as checksum provenance; the root workspace's dependency sections state the direct set and kinds. A git/tarball/file locator is recorded WITHOUT a version (the locator is kept as provenance) as an un-matchable component — an npm identity is never invented from a locator — and workspace: entries are the project's own code, never fabricated into packages. Declared overrides and patchedDependencies are recorded as EVIDENCE (bun-override/bun-patch provenance on the affected components plus an informational warning): a patched dependency keeps its registry identity — the patch is a recorded fact for human review, never a new component. trustedDependencies (the lifecycle-script allowlist — reviewer-relevant supply-chain evidence) and catalog/catalogs (workspace version catalogs; stated SPECIFIERS, never resolved-version claims) are recorded the same way, as bun-trusted/bun-catalog provenance plus informational warnings. The binary bun.lockb stays recognized-unsupported. | ||
Cargo.lock | cargo | Lockfile | — | ||
Podfile.lock | cocoapods | Lockfile | CocoaPods resolved pods for an Apple-platform product (iOS/macOS/watchOS/tvOS). Each PODS row becomes its own component: a SUBSPEC (Firebase/Core) is NEVER merged into its parent pod, because CocoaPods can pin them to different versions. The parent pod's SPEC CHECKSUMS digest is recorded WHOLE as sha1 provenance — recorded metadata for review, never an authenticity proof and never truncated; nothing is fetched or verified. A pod with no RESOLVED version (a requirement or an external from reference in the version position) is recorded WITHOUT one, with the stated value preserved verbatim, and reported by lockfile_pin_without_release_version — a range is never collapsed into an invented point version. A pod path repeated at two versions keeps BOTH components and raises version_conflict; the file is never reduced to a last-wins answer. HONEST LIMIT — purl identity: purl-spec defines a cocoapods type, but it puts the subspec in the purl SUBPATH and prohibits a namespace, and SBOMFlow's component model has no subpath axis, so pods are recorded as pkg:generic/<parent>/<subspec>@<version> with the pod path verbatim rather than as a purl shape the spec does not define. Either way osv.dev serves no CocoaPods ecosystem, so pods carry match_scope: none and are counted as not-matchable in observation-coverage.json. The stated COCOAPODS: tool version is read verbatim and surfaced by unsupported_lockfile when it is not a major release this parser was written against. | ||
composer.lock | composer | Lockfile | — | ||
conan.lock | conan | Lockfile | — | ||
deno.lock | deno | Lockfile | Deno's lockfile, versions 4-5 (older shapes are warned about by version, never guessed at). npm entries become pkg:npm/<name>@<version> (OSV-matchable, SRI integrity kept); jsr entries are real registry coordinates but JSR has no purl type or OSV ecosystem yet, so they are recorded with the stated name/version as un-matchable generic components — a WATCHLIST row: they promote to an ecosystem-native, advisory-matchable identity the day purl-spec or OSV adds JSR, and nothing is speculated until then; clean remote module URLs are recorded as un-matchable URL components without a version (URL + stated sha256 kept as provenance). The workspace block states the direct set where present. | ||
dependencies.lock | esp-idf | Lockfile | ESP-IDF managed components (ESP Component Manager), with their component_hash as checksum provenance. Package URL defines NO type for ESP-IDF, so these are recorded honestly as pkg:generic/<namespace>/<name> — SBOMFlow will not invent a purl type or file them under another ecosystem. They are full inventory (name, exact version, checksum, direct/transitive scope) but no advisory database is keyed by these coordinates: they carry match_scope: none and are counted as not-matchable in observation-coverage.json. | ||
go.mod | go | Lockfile | — | ||
go.sum | go | Lockfile | — | ||
Chart.lock | helm | Lockfile | Helm resolved subcharts: each dependencies entry (name, repository, version) becomes a direct component; a subchart's own dependencies are in that subchart's lock, not this one. Identity is (repository, chart name): for a network location (https://, oci://) the host and path become the purl namespace and the stated repository is kept verbatim as the repository_url qualifier, so one chart name from two repositories stays two components. An @name/alias:name reference and a file:// path are recorded verbatim as provenance and never read or resolved. A repository carrying userinfo, a query or a fragment is WITHHELD whole — it reaches no identity, qualifier, provenance or message — and the fact is reported. Only a resolved point version is recorded: Helm copies the Chart.yaml constraint through for a vendored subchart, so a range is kept verbatim with an EMPTY version and reported by lockfile_pin_without_release_version; a value the YAML reader typed (an unquoted 1.10) is left empty rather than recorded altered. A repeated entry is recorded once and reported, one chart at two versions keeps both and raises version_conflict. The top-level digest covers the dependency SET, not any chart, so it is recorded verbatim as helm-lock-digest provenance — never a checksum, never recomputed, never an authenticity proof. generated is Helm's run time and is not recorded (the file's own SHA-256 keeps it). HONEST LIMIT — no helm purl type is registered and no advisory source is keyed by chart coordinates, so subcharts are pkg:generic with match_scope: none; the images a rendered chart pulls are not in this file. Chart.yaml stays recognition-only. | ||
mix.lock | hex | Lockfile | Elixir Hex resolved dependencies (Nerves/embedded Elixir). :hex entries become pkg:hex/<name>@<version> with the stated archive sha256 as checksum provenance and dependency edges from each entry's deps list. A :git entry is recorded WITHOUT a version (the revision is kept as provenance) as an un-matchable component — a Hex identity is never invented from a commit. Supersedes the declared mix.exs (recognized, not parsed). | ||
rebar.lock | hex | Lockfile | Erlang rebar3's resolved lock (BEAM / embedded Erlang). It is an Erlang-terms document, read with anchored patterns — rebar3 is never evaluated. {pkg,<name>,<version>} entries are Hex registry coordinates → pkg:hex/<name>@<version> (the same served chain as mix.lock: the official hex purl type and OSV's Hex ecosystem), keyed by the pkg tuple's registry name, with the pkg_hash_ext (outer, hex.pm-canonical; pkg_hash is the inner fallback) checksum kept as provenance and a Level-0 pin recorded as a direct dependency edge. A git/hg entry ships from a repository, so it is recorded WITHOUT a version (the revision is kept as provenance) as an un-matchable generic component — a Hex identity is never invented from a commit. The declared rebar.config is not parsed. | ||
gradle.lockfile | maven | Lockfile | — | ||
project.assets.json | msbuild | Lockfile | NuGet restore's resolved-assets graph for an MSBuild project (written by every dotnet restore under obj/ — it complements packages.lock.json, which most projects do not commit). Resolved package libraries become pkg:nuget/<name>@<version> with the stated sha512 as checksum provenance; project references are the workspace's own code and are never fabricated into packages. Direct-vs-transitive is recorded only when the project section states it. | ||
flake.lock | nix | Lockfile | Nix flake locked inputs. Only a github/gitlab input with a pinned rev has an official purl-typed coordinate (pkg:github/<owner>/<repo>@<rev>); every other locked type (git URL, tarball, path) is recorded as an un-matchable component named by the flake's own input label, without a version — an identity is never guessed from a URL. The stated narHash is recorded verbatim as integrity provenance. All flake components carry match_scope: none: no advisory database is keyed by these coordinates. | ||
npm-shrinkwrap.json | npm | Lockfile | — | ||
package-lock.json | npm | Lockfile | — | ||
pnpm-lock.yaml | npm | Lockfile | pnpm's resolved graph (v9 maps; earlier package-map shapes are read where recognizable). Locked packages become pkg:npm/<name>@<version> with importer-stated direct/dev axes. Root overrides and patchedDependencies declarations are recorded as EVIDENCE (pnpm-override/pnpm-patch provenance on the affected components plus an informational warning), exactly the bun.lock pattern: an exact name@version patch attaches to that version, a bare-name or name@* patch attaches to every resolution of the name (pnpm's own application rule), and a name@<range> patch is stated verbatim in the warning but never guessed onto components. An empty-range convergence override (name@, pnpm's all-versions form) is recorded with its verbatim selector and that documented meaning. Root catalogs (v9 workspace version catalogs) are recorded the same way, as pnpm-catalog provenance: pnpm names both the shared specifier and the version it resolved to, so each declaration attaches to that exact resolved component. Identity is never altered by a declaration. | ||
yarn.lock | npm | Lockfile | Yarn Classic v1 resolved graph (Yarn Berry lockfiles are recognized and honestly refused). HONEST LIMIT — resolutions overrides: Yarn's override mechanism lives in package.json, not in yarn.lock, so the lockfile alone never states the override declaration. SBOMFlow records the resolved graph the lockfile DOES state and does not half-parse the manifest to guess at override evidence — unlike bun.lock and pnpm-lock.yaml v9, which write their override/patch declarations into the lockfile itself and get override/patch evidence rows. | ||
packages.config | nuget | Lockfile | Legacy NuGet packages.config — the flat XML installed set of a .NET Framework project (the long-lived industrial/OT tail). Each <package id version targetFramework/> states an EXACT installed version, so it is resolved lockfile-class (its versions supersede a declared source for the same identity) and yields pkg:nuget/<id>@<version> — the same served chain as packages.lock.json. targetFramework and allowedVersions (a range, never the point version) are recorded as provenance; developmentDependency="true" records the dev kind. New-style PackageReference projects use project.assets.json (also parsed); the two are different project styles, so neither supersedes the other. | ||
packages.lock.json | nuget | Lockfile | — | ||
cpanfile.snapshot | perl | Lockfile | Carton's resolved Perl snapshot. Each distribution stanza becomes pkg:cpan/<Dist>@<version> (the official cpan purl type, keyed by the case-sensitive distribution name; the CPAN pathname — author id included — is kept as provenance). CPAN is NOT an OSV ecosystem (live-checked: the osv.dev API rejects it), so these components carry an honest match_scope: none — full inventory, no advisory-match claim. provides/requirements joins yield dependency edges. Supersedes the declared cpanfile (recognized, not parsed). | ||
pubspec.lock | pub | Lockfile | Dart pub's resolved set. Only hosted packages are registry coordinates, so only they get pkg:pub/<name>@<version> identity (with the stated sha256 as checksum provenance and the dependency field's direct/dev/transitive axes recorded). A git/path/sdk dependency is recorded with the version and provenance the lockfile states, but as an un-matchable generic component — a pub.dev identity is never invented for it. Supersedes the declared pubspec.yaml (recognized, not parsed). | ||
Pipfile.lock | python | Lockfile | — | ||
poetry.lock | python | Lockfile | — | ||
uv.lock | python | Lockfile | — | ||
renv.lock | renv | Lockfile | R renv's resolved environment. Only a package the lockfile itself places on CRAN (Source: Repository + Repository: CRAN) gets pkg:cran/<name>@<version> — CRAN is a published OSV ecosystem, so those are advisory-matchable. A Source: Bioconductor package (the literal renv's own writer emits) keeps a pkg:generic purl — purl-spec defines NO bioconductor type and one is never invented — but carries the bioconductor ecosystem label: Bioconductor is an osv-schema DEFINED ecosystem, so these match by ecosystem + name in the offline snapshot matcher (match_scope: registry; the online purl client honestly counts them as skipped). osv.dev does not currently SERVE a Bioconductor ecosystem, so no advisory is found in practice today; the path is fail-safe and retained deliberately (issue #482). A completely pinned GitHub/GitLab/Bitbucket remote on the PUBLIC forge becomes `pkg:github | gitlab | bitbucket/<owner>/<repo>@<sha> (official purl types, honest match_scope: none, the flake.lock precedent); every other source (Local, URL, non-CRAN repositories, incomplete pins, self-hosted forge hosts) is recorded with the stated name/version as an un-matchable generic component — a CRAN, Bioconductor or public-forge identity is never invented. Requirements yields dependency edges; renv's own Hash` is kept verbatim as integrity provenance. |
Gemfile.lock | rubygems | Lockfile | — | ||
Package.resolved | swiftpm | Lockfile | SwiftPM resolved pins, schema v1/v2/v3. Components carry the official swift purl type (pkg:swift/github.com/Alamofire/Alamofire@5.4.3). A pin resolved to a branch/commit has no release version, so it is recorded WITHOUT a version (the commit is kept as provenance) rather than having one invented; it is reported by the lockfile_pin_without_release_version warning. | ||
library.properties | arduino | Manifest | An Arduino library's own metadata (name=/version= are mandatory in the Arduino library specification): exact evidence that a copy of that library is vendored in the tree (the source-header precedent). Arduino has no purl type, so the component is pkg:generic/<name> with match_scope: none; depends= declarations are provenance, never fabricated into components. | ||
host-manifest.csv | buildroot | Manifest | Buildroot legal-info host-tool manifest; source scope stays host and never enters the shipped set by name. The optional first-party external-tree target preserves it. Structural ambiguity is reported and never repaired, on the same terms as the opkg, vcpkg and Yocto rows. Two shapes are named: a data row carrying MORE cells than the header declares, which is the signature of a lost row separator (legal-manifest in package/pkg-utils.mk writes one double-quoted field per header column, so a row is never legitimately longer); and a header naming one column this reader USES twice, where the reader takes the first index and a row states different values across the two positions. Cells are compared as CSV cells, never raw commas: a real LICENSE or DEPENDENCIES WITH LICENSES value routinely contains quoted commas. Extra and reordered columns stay legitimate — columns are located by header name on purpose, and the header itself gained DEPENDENCIES WITH LICENSES in Buildroot 2018.11. A merged row is NOT split, so a package the file names is absent from the component list, and the extra cells are recorded verbatim in the warning, attributed to no package. | ||
manifest.csv | buildroot | Manifest | Buildroot legal-info target-package manifest. The optional first-party integrations/buildroot external-tree target collects it without analysis. Its linux row also yields the kernel as a linux-kernel component (its VERSION is the kernel source version; linux-headers is not the kernel) — see the modules.dep row. Structural ambiguity is reported and never repaired, on the same terms as the opkg, vcpkg and Yocto rows. Two shapes are named: a data row carrying MORE cells than the header declares, which is the signature of a lost row separator (legal-manifest in package/pkg-utils.mk writes one double-quoted field per header column, so a row is never legitimately longer); and a header naming one column this reader USES twice, where the reader takes the first index and a row states different values across the two positions. Cells are compared as CSV cells, never raw commas: a real LICENSE or DEPENDENCIES WITH LICENSES value routinely contains quoted commas. Extra and reordered columns stay legitimate — columns are located by header name on purpose, and the header itself gained DEPENDENCIES WITH LICENSES in Buildroot 2018.11. A merged row is NOT split, so a package the file names is absent from the component list, and the extra cells are recorded verbatim in the warning, attributed to no package. | ||
Cargo.toml | cargo | Manifest | Each dependency it declares is inventoried and recorded as a direct dependency of the product (an edge from the product root, source manifest); where a lockfile resolves it, the lockfile's resolved identity and its own edges stand. Every version string it states is a requirement, not a version (a bare 1.2.3 is ^1.2.3): it is kept as written with no version, and only Cargo.lock gives the version. A renamed dependency is the crate its package key names. The platform-specific tables ([target.'cfg(...)'.dependencies], [target.<triple>.dependencies] and their dev- and build- forms) and the table form [dependencies.<name>] are read too, a platform-specific dependency keeping its target as context, never identity; [workspace.dependencies], which only defines what members inherit, is named under unrecognized_manifest_format and not read as dependencies. A path dependency (path = "../cli") is a local crate: its path is kept as a local-path provenance entry and it takes the [package] version of the Cargo.toml at that path, matched by path and name, or else its one source-less Cargo.lock entry, the source recorded as cargo-path-version; with neither it stays versionless, is named, and as first-party source is not matched against the public crate's advisories. | ||
*.cmake (glob) | cmake | Manifest | — | ||
CMakeLists.txt | cmake | Manifest | FetchContent_Declare / ExternalProject_Add declared sources, read statically — CMake is never run and ${...} is never expanded. At most 2000 declarations are READ per file, whether or not any of them parse; past that the file is truncated and a warning says so, so a hostile or generated file cannot make the scan unbounded. A declaration that cannot be read is warned about individually and never guessed at. | ||
*.cbuild-pack.yml (glob) | cmsis-pack | Manifest | CMSIS-Toolbox pack lock (YML-CBuild-Format): the exact pack versions the toolbox resolved for the solution. Read as the resolved source, so its versions supersede the version-less pack: selections of the solution files in the merge; an entry without an exact version is refused. | ||
*.clayer.yml (glob) | cmsis-pack | Manifest | CMSIS-Toolbox project file (YML-Input-Format, Apache-2.0). pack: selections (vendor::name[@version]) and component: selections ([Cvendor::]Cclass[&Cbundle]:Cgroup[:Csub][&Cvariant][@[>=]Cversion]) become pkg:generic components with match_scope: none. Only an exact @version is a version; >=, ^ and ~ ranges are kept verbatim as raw_version. A wildcard or vendor-only pack selection names no single pack and is skipped with a warning. The pack versions the toolbox resolved come from *.cbuild-pack.yml. | ||
*.cproject.yml (glob) | cmsis-pack | Manifest | CMSIS-Toolbox project file (YML-Input-Format, Apache-2.0). pack: selections (vendor::name[@version]) and component: selections ([Cvendor::]Cclass[&Cbundle]:Cgroup[:Csub][&Cvariant][@[>=]Cversion]) become pkg:generic components with match_scope: none. Only an exact @version is a version; >=, ^ and ~ ranges are kept verbatim as raw_version. A wildcard or vendor-only pack selection names no single pack and is skipped with a warning. The pack versions the toolbox resolved come from *.cbuild-pack.yml. | ||
*.csolution.yml (glob) | cmsis-pack | Manifest | CMSIS-Toolbox project file (YML-Input-Format, Apache-2.0). pack: selections (vendor::name[@version]) and component: selections ([Cvendor::]Cclass[&Cbundle]:Cgroup[:Csub][&Cvariant][@[>=]Cversion]) become pkg:generic components with match_scope: none. Only an exact @version is a version; >=, ^ and ~ ranges are kept verbatim as raw_version. A wildcard or vendor-only pack selection names no single pack and is skipped with a warning. The pack versions the toolbox resolved come from *.cbuild-pack.yml. | ||
*.pdsc (glob) | cmsis-pack | Manifest | CMSIS-Pack description, read per the Open-CMSIS-Pack specification (PACK.xsd, Apache-2.0): a .pdsc in the tree is the pack's own description, so it is recorded as ONE component pkg:generic/<vendor>/<name>@<version> at the release on top of <releases>, with the <repository> URL as provenance. The components a pack DEFINES are not recorded: a definition is not a selection. A schemaVersion whose major is not 1 is refused by name; a DOCTYPE is refused; only the header elements are read. | ||
firmware-manifest.txt | generic | Manifest | SBOMFlow's own three-column product manifest, name,version,ecosystem. Structural ambiguity is reported and never repaired, on the same terms as the opkg, vcpkg and Yocto rows: a row carrying a fourth POPULATED column is the signature of a lost newline fusing two rows into one. Such a row is NOT split — guessing where the newline belonged would invent inventory — so a component the file names is absent from the component list, and the extra columns are recorded verbatim in the warning, attributed to no component. An EMPTY extra column discards nothing and is not reported. | ||
product-manifest.txt | generic | Manifest | SBOMFlow's own three-column product manifest, name,version,ecosystem. Structural ambiguity is reported and never repaired, on the same terms as the opkg, vcpkg and Yocto rows: a row carrying a fourth POPULATED column is the signature of a lost newline fusing two rows into one. Such a row is NOT split — guessing where the newline belonged would invent inventory — so a component the file names is absent from the component list, and the extra columns are recorded verbatim in the warning, attributed to no component. An EMPTY extra column discards nothing and is not reported. | ||
.gitmodules | git | Manifest | Git submodules the tree declares (gitmodules(5), git-config syntax), read statically: git is never run and nothing is fetched. Each submodule becomes a declared pkg:generic component named by the repository its url states, with the host and owner path of an absolute URL as the namespace, and an honest match_scope: none (the rule for every git-sourced dependency). NO VERSION is recorded: the pinned commit lives in the superproject's git tree, not in this file, and SBOMFlow has no operator input that supplies it, so provenance says the commit is not established; a branch is kept as provenance, never as a version. A credential in the URL is withheld. A file git cannot parse is refused whole; a submodule git would reject (a .. name or path, an absolute path, an option-like value, a missing url/path) or one stating a key twice with different values is skipped with a warning. Keys outside gitmodules(5), such as a project's own sbom-* annotations, are not read. | ||
manifest.toml | gleam | Manifest | gleam's resolved dependency lock (BEAM; gleam publishes to Hex). Content-sniffed to distinguish it from Julia's Manifest.toml (capital M) — a packages array stating source = "hex" is gleam and is parsed, never claimed by the bare name. source = "hex" packages become pkg:hex/<name>@<version> (the served Hex chain, mix.lock's identity) with the stated outer_checksum as sha256 provenance; a git/local package is recorded with its stated name/version as an un-matchable pkg:generic component — a Hex identity is never invented. The top-level [requirements] marks the direct set and each package's requirements list yields dependency edges. Julia's Manifest.toml stays a recognized-unparsed row. | ||
go.mod | go | Manifest | Each require is applied through replace as the build applies it. A module required at a placeholder (v0.0.0, or the zero pseudo-version v0.0.0-00010101000000-000000000000) and replaced by a directory of the tree (replace k8s.io/api => ./staging/src/k8s.io/api) is first-party source: its directory is kept as a local-path provenance entry, it is recorded with no version, and it is not matched against the public module's advisories. A released version or a pseudo-version naming a real commit replaced by a local copy, or a directory outside the tree, is a copy of the public module and is matched at unknown version. | ||
verification-metadata.xml | maven | Manifest | Gradle's dependency-verification list (item 331): the artifacts a build verifies, with their checksums — not the resolved dependency graph. Every row it produces says so; pair it with gradle.lockfile for the resolved set. | ||
_manifest.xml | mcuxpresso | Manifest | NXP MCUXpresso SDK manifest (<device-or-board>_manifest_v3_<n>.xml). CONTENT-SNIFFED: only an .xml whose name contains manifest and whose head is a manifest root stating format_version with a ksdk element is claimed; any other XML is left alone. Read per NXP's published sdk_manifest_v3.x.xsd (3.0 to 3.10 are published): ONE component, the SDK package the manifest identifies (root id) at the ksdk version. The components the manifest lists are what the SDK distribution contains, not what a build selected, so they are not recorded. A format_version with no published schema is refused by name; a DOCTYPE is refused; only the header is read. A manifest above the 5 MB text-scan cap is hashed, not read. | ||
package.json | npm | Manifest | Each dependency it declares is inventoried and recorded as a direct dependency of the product (an edge from the product root, source manifest); where a lockfile resolves it, the lockfile's resolved identity and its own edges stand. | ||
Dockerfile | oci | Manifest | — | ||
compose.yaml | oci | Manifest | Docker/Podman Compose file (the Compose Specification's preferred name). services.*.image references become pkg:docker components, mirroring the Dockerfile FROM rows; build:-only services and ${VAR} interpolations are recorded as no image (never guessed). | ||
compose.yml | oci | Manifest | — | ||
docker-compose.yaml | oci | Manifest | — | ||
docker-compose.yml | oci | Manifest | — | ||
platformio.ini | platformio | Manifest | PlatformIO lib_deps library declarations, read statically (the CMake-declares precedent): interpolations are never expanded and the registry is never queried. PlatformIO has no purl type, so declared libraries are recorded as pkg:generic/<owner>/<name> with match_scope: none; version ranges are neutralized into raw_version, never presented as point versions. | ||
requirements.txt | python | Manifest | Every pip requirements file: pip's documented names (requirements-dev.txt, requirements_all.txt, any .txt directly in a requirements/ directory) are read exactly as requirements.txt is; any other name containing requirements (dev-requirements.txt) is read only when every line is a pip requirement line (PEP 508 with PEP 440 versions, an option, a URL such as git+https://…, or a local project path); otherwise it is named with a warning under unrecognized_manifest_format and not read on its own, though a requirements file that includes it with -r still reads it. Each component keeps the file that declared it, no dependency kind is guessed from a file name, and a file read on its own and also reached through -r is counted once. | ||
requirements.txt | python | Manifest | Each dependency it declares is inventoried and recorded as a direct dependency of the product (an edge from the product root, source manifest); where a lockfile resolves it, the lockfile's resolved identity and its own edges stand. An environment marker (; python_version<"3.9") is kept beside the component exactly as written, as a pip-environment-marker provenance entry, and never evaluated: whether the dependency is used depends on the product's deployment environment, not the scanning host. | ||
*.slcp (glob) | silabs-slc | Manifest | Silicon Labs SLC project, read per the published SLC Specification (1.4): the sdk and each sdk_extension at the version stated, and each selected component by its id (namespaced by its package/from extension when stated) with NO version: the file states none, and the SDK's version is never assigned to a component. pkg:generic, match_scope: none. | ||
vcpkg.json | vcpkg | Manifest | — | ||
*.manifest (glob) | yocto | Manifest | Yocto image package manifest; the optional first-party meta-sbomflow layer preserves its exact bytes for later offline ingestion. The kernel-<release> package kernel.bbclass names after the kernel release (every virtual/kernel provider inherits it) also yields the kernel as a linux-kernel component — see the modules.dep row; kernel-module- and kernel-image- packages do not. | ||
license.manifest | yocto | Manifest | Yocto image licence manifest. The optional first-party meta-sbomflow layer collects it from kirkstone/scarthgap LTS builds without analysing it in BitBake. Structural ambiguity is reported and never repaired, on the same terms as the opkg and vcpkg rows: a field stated twice with different values (last-wins discards the earlier one), and a record stating its package identity field more than once, which is the signature of a lost blank-line separator left by an interrupted write. Such a record is NOT split — guessing where the separator belonged would invent inventory — so a package the file names is absent from the component list, and the surviving record's LICENSE: value is kept verbatim in the warning but not attributed to it. The identity is whichever field named the package (PACKAGE NAME:, or RECIPE NAME: in the image-manifest variant), counted by its own LINES: every healthy record states both spellings, so treating them as one counter would report a merged record on every real Yocto build. The repeated-field report is likewise scoped to the fields this reader consumes and license_image.bbclass writes once per record. | ||
west.yaml | zephyr | Manifest | Zephyr west manifest. Structural ambiguity is reported and never repaired, on the same terms as the opkg, vcpkg and Yocto rows: a key stated twice inside ONE YAML mapping is folded last-wins by PyYAML and by the bundled loader before this parser sees the document, and west itself cannot report it either because its schema validation runs on the already-folded mapping. Both backends answer with the same detail — the value the repeat discarded, the value that survived it, and the mapping the repeat happened in — so no part of the report depends on whether the optional PyYAML extra is installed. The record-bearing keys (manifest, projects, name) are counted by LINES; the value keys (defaults, revision) are reported only when the repeat actually CHANGED the value, because a restatement of the identical value discards nothing. Reporting is scoped to the mapping each key is READ in, never to the key's spelling: name: legitimately recurs once per remote and once per project — 82 times in Zephyr's own manifest — revision: recurs inside every submodules: entry, and userdata: is typed any by west's schema, so a per-file occurrence count would fire on every healthy workspace. The document is NOT split, so a project the file names is absent from the component list, and the discarded statement is quoted verbatim from the source line, attributed to no project. A record that states its name: twice is two projects fused by a lost separator, so its own revision: is not attributed to the surviving name either — that project is recorded with the manifest default, or unpinned — while every other project in the file keeps the revision it states. | ||
west.yml | zephyr | Manifest | Zephyr west manifest. Structural ambiguity is reported and never repaired, on the same terms as the opkg, vcpkg and Yocto rows: a key stated twice inside ONE YAML mapping is folded last-wins by PyYAML and by the bundled loader before this parser sees the document, and west itself cannot report it either because its schema validation runs on the already-folded mapping. Both backends answer with the same detail — the value the repeat discarded, the value that survived it, and the mapping the repeat happened in — so no part of the report depends on whether the optional PyYAML extra is installed. The record-bearing keys (manifest, projects, name) are counted by LINES; the value keys (defaults, revision) are reported only when the repeat actually CHANGED the value, because a restatement of the identical value discards nothing. Reporting is scoped to the mapping each key is READ in, never to the key's spelling: name: legitimately recurs once per remote and once per project — 82 times in Zephyr's own manifest — revision: recurs inside every submodules: entry, and userdata: is typed any by west's schema, so a per-file occurrence count would fire on every healthy workspace. The document is NOT split, so a project the file names is absent from the component list, and the discarded statement is quoted verbatim from the source line, attributed to no project. A record that states its name: twice is two projects fused by a lost separator, so its own revision: is not attributed to the surviving name either — that project is recorded with the manifest default, or unpinned — while every other project in the file keeps the revision it states. | ||
curlver.h | vendored | Source header | — | ||
init.h | vendored | Source header | — | ||
opensslv.h | vendored | Source header | — | ||
png.h | vendored | Source header | — | ||
sqlite3.h | vendored | Source header | — | ||
task.h | vendored | Source header | — | ||
version.h | vendored | Source header | — | ||
zlib.h | vendored | Source header | — |
Dependency scope and kind#
Every observed component carries two orthogonal scope axes, and SBOMFlow only fills in what the lockfile actually states. Neither is ever guessed.
dependency_scope— the relationship:direct,transitive, orunknown.dependency_kind— how the dependency is used:runtime,dev, oroptional. Empty means the lockfile does not record it, not "runtime".
| Lockfile | dependency_scope | dependency_kind | Where the kind comes from |
|---|---|---|---|
package-lock.json, npm-shrinkwrap.json | direct / transitive | runtime / dev / optional | per-package dev, optional, devOptional flags |
pnpm-lock.yaml | direct / transitive | direct deps only | the importer section (dependencies / devDependencies / optionalDependencies); v5 per-package dev/optional flags |
Pipfile.lock | unknown | runtime / dev | the default vs develop category |
composer.lock | unknown | runtime / dev | the packages vs packages-dev array |
poetry.lock | unknown | runtime / dev | category (Poetry < 1.5) or groups (≥ 1.5) |
go.mod | direct / transitive | not recorded | Go has no dev-dependency concept |
gradle.lockfile | unknown | not recorded | the lock states Gradle configurations (runtimeClasspath, testCompileClasspath, …), not a runtime/dev axis — mapping one onto the other would be a guess |
Gemfile.lock | direct / transitive | not recorded | groups live in the Gemfile, not the lock |
packages.lock.json (NuGet) | direct / transitive | not recorded | — |
packages.config (legacy NuGet) | unknown | dev only | developmentDependency="true"; the flat installed list marks no direct/transitive axis |
Cargo.lock | unknown | not recorded | the lock does not distinguish dev-dependencies; Cargo.toml, below, states them |
yarn.lock (classic) | unknown | not recorded | — |
conan.lock, uv.lock | unknown | not recorded | — |
pubspec.lock | direct / transitive | runtime / dev | pub's own dependency field (direct main / direct dev / transitive); direct overridden states the scope but no kind |
mix.lock | unknown | not recorded | the lock states resolved coordinates, not a runtime/dev axis (that lives in mix.exs, which is not parsed) |
flake.lock | direct / transitive | not recorded | the root node's inputs positively state the direct set; Nix has no dev-dependency axis here |
project.assets.json | direct / transitive / unknown | not recorded | direct only when project.frameworks.<tfm>.dependencies states it; otherwise unknown, never guessed |
renv.lock | unknown | not recorded | renv states no direct/dev axis (the DESCRIPTION does; it is not parsed) |
cpanfile.snapshot | unknown | not recorded | the snapshot states resolved distributions, not a runtime/develop axis (that lives in the cpanfile, which is not parsed) |
bun.lock | direct / transitive | direct deps only | the workspace sections (dependencies / devDependencies / optionalDependencies); transitive packages record no kind |
deno.lock | direct / transitive / unknown | not recorded | direct only when the workspace block states its dependency set; otherwise unknown, never guessed |
package.json (no lockfile) | not recorded | dev / optional | the section: devDependencies -> dev, optionalDependencies -> optional; dependencies and peerDependencies state no kind, and a name also under dependencies never takes a weaker one. An alias npm:<name>@<spec> is the package it installs; a dist-tag (latest) is recorded without a version |
Cargo.toml | not recorded | dev only | the table: a crate named only under [dev-dependencies] or [build-dependencies] (any [target.<spec>.…] form, or the table form) -> dev; the Cargo reference says dev-dependencies "are not used when compiling a package for building" and build dependencies are "not available to the package itself". [dependencies] states no kind, and a crate also named there (any target, or through a rename) never takes a weaker one |
Notes on the honest edges:
- A pnpm transitive package in a v6/v9 lockfile records no kind. Propagating a parent's kind down the graph would be a guess, so it stays empty.
- npm marks a package
devOptionalwhen it is reachable through both a dev and an optional edge. npm cannot say which edge installed it, so SBOMFlow records the weaker shipping claim,optional. - Poetry: a package in
mainanddevships, somainwins. An unrecognized group is left empty rather than collapsed intodev. - When several sources describe one component,
runtimewins, thenoptional;devis the answer only when every source that stated a kind saiddev. - A
devkind is removed — to no kind, never toruntime— when something observed says the component may ship: aCargo.tomlorpackage.jsonthat contributed to it declares the same name as a normal dependency (measured: one manifest's devDependency and another's dependency used to merge todev), or, for Cargo, whose lock states no kind, a dependency edge reaches it from a component that is not itselfdev(a dev-dependencytokioalso reached throughreqwestships). An edge from the product root says nothing either way. The same rule holds when thedevcomes from a supplier SBOM given with--import-sbom(a CycloneDXscope: excluded, an SPDX development or test role): it is removed when the tree's own manifest or lockfile says the component ships, and kept where nothing observed contradicts it.
Kind informs policy only. A dev dependency is still observed, still in the SBOM, and still matched against advisories — it is never dropped from the composition. In CycloneDX the kind maps to the standard scope field (runtime→required, optional→optional, dev→excluded); when the kind is unknown, no scope is asserted at all.
Opt-in scope-aware gating#
By default the release gate blocks on every scope, exactly as before. A gate policy may set:
policy:
exclude_dev_dependency_findings: trueWith that set, a finding whose component was positively observed as a dev dependency no longer blocks the release. It is still reported in evidence-pack.json and issues.json, and the exemption is recorded in release-gate.json under dev_dependency_exempt_ids and shown by sbomflow explain <dir> --gate. A component whose kind is unknown always still blocks — the policy can only waive what the lockfile positively identified.
Recognized but not parsed yet (77 warn, never silent)#
Each surfaces an actionable warning naming the exact file; use the matching opt-in importer where one exists, or review the recorded file manually.
| Input | Family | Kind | Notes |
|---|---|---|---|
.config | kconfig | Build evidence | Retained and hashed; use the matching build-evidence importer. |
*.map.summary.json (glob) | linker-map | Build evidence | — |
colcon-events.log | ros2 | Build evidence | — |
*.ioc (glob) | stm32cube | Build evidence | STM32CubeMX project configuration. Recognised, hashed and warned about, and NOT read: no public ST document defines the .ioc keys and the tool that defines them is not OSI-licensed, so there is no basis to read even the firmware-package key. It yields no component; the STM32Cube firmware package is visible only through another input (a CMSIS-Toolbox project, a vendored library's version header, or an imported SBOM). |
zephyr.meta.json | zephyr | Build evidence | — |
index.json | oci | Container | A layout found in the scanned tree is warned about and never read as an image. The images a release ships are declared under release.container_images in sbomflow.yaml, which records each reference and digest in release-record.json and compares the digest with the local layout or image tarball named there; oci-evidence reads one layout on its own. |
oci-layout | oci | Container | A layout found in the scanned tree is warned about and never read as an image. The images a release ships are declared under release.container_images in sbomflow.yaml, which records each reference and digest in release-record.json and compares the digest with the local layout or image tarball named there; oci-evidence reads one layout on its own. |
*.dts (glob) | device-tree | Device tree | — |
*.dtsi (glob) | device-tree | Device tree | — |
bun.lockb | bun | Lockfile | Bun's binary lockfile. Recognized by name so it warns instead of falling to hash-only — a binary format is still a named format. The text bun.lock IS parsed; Bun >= 1.2 writes it by default and bun install --save-text-lockfile migrates. |
conda-lock.yml | conda | Lockfile | conda-lock's fully-resolved lockfile. Bare environment.yml is deliberately NOT claimed: that name is a generic convention far beyond conda, so a name-only claim would mislabel unrelated YAML. |
shard.lock | crystal | Lockfile | A Crystal shards lockfile. Resolved, with no purl type or advisory ecosystem to match it against. |
cabal.project.freeze | haskell | Lockfile | — |
stack.yaml.lock | haskell | Lockfile | — |
Manifest.toml | julia | Lockfile | Julia Pkg's resolved environment (the exact capitalized name is the Pkg convention). |
pom.xml | maven | Lockfile | Unsupported by design (item 209): a pom declares dependencies whose versions come from parent poms, BOM imports and properties, so resolving the real coordinate set requires the network. SBOMFlow refuses to guess. Lock your build with gradle.lockfile (parsed), or generate a CycloneDX/SPDX SBOM from your build (e.g. the CycloneDX Maven plugin) and import it with --import-sbom. |
nimble.lock | nim | Lockfile | A Nim nimble lockfile. Genuinely resolved, but purl-spec defines no nim type and OSV serves no Nim ecosystem. |
requirements.lock | python | Lockfile | — |
default.xml | aosp | Manifest | Recognized only when the content carries repo-tool manifest markers (<manifest> with <remote> and <project> elements) — 'default.xml' alone is far too generic a name to claim. |
BUILD.bazel | bazel | Manifest | — |
MODULE.bazel | bazel | Manifest | — |
WORKSPACE | bazel | Manifest | — |
WORKSPACE.bazel | bazel | Manifest | — |
deps.edn | clojure | Manifest | A Clojure CLI dependency map. Declared coordinates only: the resolved set lives in the classpath cache, not in this file. |
project.clj | clojure | Manifest | A Leiningen project file. It is executable Clojure, so it is recognised and never parsed. |
Podfile | cocoapods | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses Podfile.lock, which records the versions the package manager resolved; commit it beside Podfile or import an SBOM generated from the build with --import-sbom. |
composer.json | composer | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses composer.lock, which records the versions the package manager resolved; commit it beside composer.json or import an SBOM generated from the build with --import-sbom. |
conanfile.py | conan | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses conan.lock, which records the versions the package manager resolved; commit it beside conanfile.py or import an SBOM generated from the build with --import-sbom. |
conanfile.txt | conan | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses conan.lock, which records the versions the package manager resolved; commit it beside conanfile.txt or import an SBOM generated from the build with --import-sbom. |
shard.yml | crystal | Manifest | A Crystal shards manifest. The declared set; shard.lock is its resolved sibling. |
libs.versions.toml | gradle | Manifest | A Gradle version catalog (conventionally gradle/libs.versions.toml). It declares Maven coordinates; the resolved set is gradle.lockfile (parsed) — declarations are never treated as inventory. |
Chart.yaml | helm | Manifest | A Helm chart's metadata (the exact capitalized name is Helm's convention). It declares version RANGES, so nothing is inventoried from it; the Chart.lock beside it states what Helm resolved and is parsed. |
mix.exs | hex | Manifest | — |
Project.toml | julia | Manifest | Julia Pkg's project manifest; Manifest.toml is the resolved set. |
build.gradle | maven | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses gradle.lockfile, which records the versions the package manager resolved; commit it beside build.gradle or import an SBOM generated from the build with --import-sbom. |
build.gradle.kts | maven | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses gradle.lockfile, which records the versions the package manager resolved; commit it beside build.gradle.kts or import an SBOM generated from the build with --import-sbom. |
meson.build | meson | Manifest | — |
default.nix | nix | Manifest | — |
flake.nix | nix | Manifest | — |
*.csproj (glob) | nuget | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses packages.lock.json, which records the versions the package manager resolved; commit it beside *.csproj or import an SBOM generated from the build with --import-sbom. |
*.fsproj (glob) | nuget | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses packages.lock.json, which records the versions the package manager resolved; commit it beside *.fsproj or import an SBOM generated from the build with --import-sbom. |
*.vbproj (glob) | nuget | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses packages.lock.json, which records the versions the package manager resolved; commit it beside *.vbproj or import an SBOM generated from the build with --import-sbom. |
distfeeds.conf | openwrt | Manifest | The on-device opkg feed list the OpenWrt build system writes. Recognized only under etc/opkg/ (the path context is the OpenWrt statement); the bare name elsewhere claims nothing. |
feeds.conf | openwrt | Manifest | OpenWrt buildroot feed declarations; the resolved installed set is the opkg status database (parsed). |
feeds.conf.default | openwrt | Manifest | The default feed list shipped in the OpenWrt source tree (feeds.conf overrides it when present). |
APKBUILD | os-recipe | Manifest | An Alpine package recipe. It BUILDS a package rather than declaring an installed set, so parsing it would report inventory the device may never have carried. |
PKGBUILD | os-recipe | Manifest | An Arch package recipe. An executable shell script that builds a package; recognised, never parsed, for the same reason as APKBUILD. |
cpanfile | perl | Manifest | The declared set. The resolved cpanfile.snapshot IS parsed — a declaration is a wish, the snapshot is the fact. |
pubspec.yaml | pub | Manifest | — |
constraints.txt | python | Manifest | A pip constraints file "only control[s] which version of a requirement is installed, not whether it is installed" (pip user guide), so no component is read from it on its own and it is named; its pins apply where a requirements file includes it with -c. |
Pipfile | python | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses Pipfile.lock, which records the versions the package manager resolved; commit it beside Pipfile or import an SBOM generated from the build with --import-sbom. |
pyproject.toml | python | Manifest | Warned only when it declares dependencies; otherwise it is not treated as inventory. |
Gemfile | rubygems | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses Gemfile.lock, which records the versions the package manager resolved; commit it beside Gemfile or import an SBOM generated from the build with --import-sbom. |
build.sbt | sbt | Manifest | An sbt build definition. It is executable Scala — the pom.xml/setup.py class — so it is recognised and never parsed. Generate a CycloneDX from the build and supply it with --import-sbom. |
Package.swift | swiftpm | Manifest | A dependency manifest SBOMFlow does not parse: it declares dependencies by range, and no component is guessed from it. It is named by file in every tree, so it is never silent beside another manifest. SBOMFlow parses Package.resolved, which records the versions the package manager resolved; commit it beside Package.swift or import an SBOM generated from the build with --import-sbom. |
build.zig.zon | zig | Manifest | A Zig package manifest (ZON). It declares dependencies with content hashes, but purl-spec defines no zig type and no advisory ecosystem serves Zig, so a parse would be un-matchable inventory. |
*.mlmodel (glob) | coreml | model-artifact | Core ML model (Protocol Buffers). A .mlpackage bundle is a directory whose inner .mlmodel/weights are recognized individually; hashed only, never parsed. |
*.gguf (glob) | gguf | model-artifact | GGUF (llama.cpp) model; parsing it is a known memory-safety surface (the GGUF integer-overflow CVE class), so it is hashed only, never parsed. |
*.onnx (glob) | onnx | model-artifact | ONNX model (Protocol Buffers); recognized by extension, hashed only, never parsed. |
*.xml (glob) | openvino-ir | model-artifact | OpenVINO IR model topology, the .xml half of an .xml+.bin pair. .xml is far too generic to claim by name, so it is recognized ONLY when the content is an IR graph (<net> with <layers>/<edges>), content-sniffed; a generic XML is never claimed. The paired .bin weights stay an opaque binary_or_firmware artifact. |
*.ckpt (glob) | pickle-checkpoint | model-artifact | Model checkpoint (PyTorch Lightning / TF). Claimed ONLY when content-sniffed as a pickle/torch-zip. Unsafe to deserialize; hashed only. |
*.joblib (glob) | pickle-checkpoint | model-artifact | joblib dump (scikit-learn and friends), commonly a pickle stream. Claimed ONLY when content-sniffed as a pickle/torch-zip; unsafe to deserialize; hashed only. |
*.pickle (glob) | pickle-checkpoint | model-artifact | Python pickle. Claimed ONLY when content-sniffed as a pickle stream. Unsafe to deserialize; hashed only. |
*.pkl (glob) | pickle-checkpoint | model-artifact | Python pickle. Claimed ONLY when the head bytes are a pickle stream — pickle deserialization executes arbitrary code (labelled unsafe_to_deserialize); hashed only, never deserialized. |
*.pt (glob) | pickle-checkpoint | model-artifact | PyTorch checkpoint. Claimed ONLY when the head bytes are a pickle stream or a torch.save zip — a text file named model.pt (Chameleon page template) is refused. Pickle deserialization executes arbitrary code (labelled unsafe_to_deserialize); hashed only, never deserialized. |
*.pth (glob) | pickle-checkpoint | model-artifact | PyTorch checkpoint. Claimed ONLY when content-sniffed as a pickle/torch-zip — a site-packages .pth path-configuration text file is refused. Unsafe to deserialize; hashed only. |
*.safetensors (glob) | safetensors | model-artifact | Hugging Face safetensors weights; recognized by extension, hashed only, never parsed. |
*.engine (glob) | tensorrt | model-artifact | TensorRT serialized engine (a hardware/version-specific plan). .plan is deliberately not claimed (generic-name collision); .engine/.trt are the TensorRT-specific surface. Hashed only, never deserialized. |
*.trt (glob) | tensorrt | model-artifact | TensorRT serialized engine (the .trt extension); hashed only, never deserialized. |
*.tflite (glob) | tflite | model-artifact | TensorFlow Lite model (FlatBuffer); recognized by extension, hashed only, never parsed. |
*.mender (glob) | mender | update-artifact | Mender Artifact (a tar archive); use mender-evidence (inspected in memory, never extracted). |
*.raucb (glob) | rauc | update-artifact | RAUC update bundle (a signed SquashFS/CMS container); use rauc-evidence on its manifest.raucm. |
manifest.raucm | rauc | update-artifact | RAUC bundle manifest (the exact name / .raucm extension is RAUC's convention). |
*.swu (glob) | swupdate | update-artifact | SWUpdate update container (a newc/crc cpio archive); use swupdate-evidence. |
sw-description | swupdate | update-artifact | SWUpdate's mandatory container member (the exact name is SWUpdate's convention). |
*.itb (glob) | uboot-fit | update-artifact | U-Boot FIT flattened image-tree blob (binary); use firmware-extract to carve its images. |
*.its (glob) | uboot-fit | update-artifact | U-Boot FIT image-tree source (device-tree syntax). Recognized only when the content is a FIT source (a /dts-v1/ document with an images or configurations node) — .its alone is not claimed. Its verified-boot signature nodes are separately surfaced as review signals; the recognition row names the file as a boot artifact. |
Imported by explicit flag (2)#
These are not auto-discovered by the scan — SBOMFlow reads them only when you pass the flag, so nothing is picked up implicitly. Each is offline, local-file-only, and hashed into the artifact manifest as provenance. Imported components carry imported provenance and never overwrite a locally-observed component; a version conflict is surfaced for a reviewer. What each reader does with every field of a document, measured on a fixture, is in the BOM family census.
| Flag | Format | Schema | Notes |
|---|---|---|---|
--import-sbom | CycloneDX 1.x JSON, SPDX 2.x JSON, SPDX 2.2/2.3 tag-value (*.spdx), SPDX 3.0.1 JSON-LD | (external standards) | Import a supplier-provided standards SBOM as observed component evidence. Components carry imported provenance and are merged with locally-observed ones without overwriting them. A component version stated as anything but a JSON string (a number such as 1.10, whose spelling parsing does not keep) is named under malformed_external_sbom_component and not read; the component is imported with no version. A version the supplier states that a local lockfile does not resolve stays its own component and is named in version_conflict; it is never folded into the lockfile's row, and it joins only the row at its own version. The serialization is chosen by CONTENT, not by file name: a .spdx holding JSON reads as JSON, and a tag-value document reads as tag-value whatever it is called. Tag-value is translated into the same SPDX 2.x model the JSON reader uses, so both forms of the same facts produce the same components; a version this build does not model (spdx_tag_value_unsupported_version) or a grammar failure (spdx_tag_value_malformed) refuses the whole document rather than returning the part that parsed, and a document declaring SPDXVersion more than once is refused because it does not say which rules it was written under. An SPDX 3 JSON-LD document's version is read from its Elements' creationInfo, inline or through the shared CreationInfo node Yocto 5.1+ writes: a newer major is refused (unsupported_spdx_spec_version) and a newer minor is imported with newer_spdx_minor_version; SPDX's own versioned JSON-LD context states the version when no creationInfo does. A document that states no version, or none in SPDX-MAJOR.MINOR form, is refused (unrecognized_external_sbom_format): which rules it follows is unknown. A UTF-8 byte-order mark is ignored once; a UTF-16 or UTF-32 export is refused by name. Non-purl identifiers a document states (CPE 2.3/2.2, SWID tag id, SWHID, OmniBOR gitoid) are recorded as identity and re-emitted; they are never used to match advisories and never derived from a component name. A package or component with no purl imports with generic identity and those identifiers, from CycloneDX and SPDX alike; an SPDX document's subject (the one package it describes) and a package it names only as a build, development or test tool stay out, and such a tool that has a purl is carried as not shipped (scope excluded). An SPDX CONTAINS between imported packages, or from the subject, is read as a dependency edge. An SPDX 3 relationship whose to is not an array is named under spdx3_document_not_fully_understood, and one whose from names no element of the document under external_sbom_dangling_dependency; neither adds an edge. A component's stated supplier and digests are carried as the document's statements, never inferred or verified; a nested CycloneDX component is imported with an edge from its parent, and a stated scope is kept as the component's kind. A CycloneDX component that declares cryptoProperties also has every value it declared recorded verbatim and bounded as the supplier's assertion, with the document's digest: SBOMFlow examines no binary and derives nothing from them. A CycloneDX 1.7 Traffic Light Protocol marking (metadata.distributionConstraints.tlp) is recorded verbatim on the document's import quality row and never enforced; because it is carried, the cyclonedx_fields_not_interpreted warning does not name it, and names any other key of that block by its own key. A CycloneDX 1.7 component whose supplier states isExternal (provided by the environment, not part of the assembly) stays in the inventory and carries the statement and any versionRange verbatim: SBOMFlow does not decide what ships, and the range is never a version and never matched. A CycloneDX compositions statement is recorded verbatim on the import quality row as the supplier's statement about its own document; a supplier's complete is never adopted as SBOMFlow's. A CycloneDX 1.7 document's citations (who asserted which field) are recorded verbatim on the import quality row, each JSON Pointer marked as resolving or not and each path expression as not evaluated; nothing is re-derived from them. |
--import-custom-manifest | SBOMFlow custom manifest | sbomflow-custom-manifest v1 | Import an explicit manufacturer-declared component + dependency handoff for evidence that cannot be reliably expressed as CycloneDX/SPDX. Every identity field is explicit; a malformed purl or missing field is warned and skipped, never guessed. See docs/CUSTOM_MANIFEST.md. |
Declaration files named by a config key (1)#
A file named under a sbomflow.yaml key is read only because the key names it; the scan never picks it up. The operator produces the file, and SBOMFlow reads it from local disk.
| Key | Format | Schema | Notes |
|---|---|---|---|
release.deployed_environment | JSON | sbomflow-deployed-environment-declaration-v1 | An operator-produced inventory of one deployed environment: environment, taken_at (ISO-8601 with an offset), source, and entries of kind image, service, host_package with a reference and an optional digest, version and count. SBOMFlow never looks at a live system. Read with the bounded reader; an unreadable file is the unreadable_file warning, and a file that is read and invalid (a repeated JSON key, an unknown key, a malformed entry or timestamp, a repeated entry, text over its bound: environment 200, source 500, reference 512, version 200 characters) refuses the run with E016. Written up as deployed-environment.json; see outputs. |
What the walk refuses to read#
- A symlink whose target resolves outside the scan root — file or directory — is never read and never descended. Each one is named by its path inside the root under
symlink_outside_rootand counted inobservation-coverage.jsonasrefused_symlink, so the inventory states what it did not read. The target path is written into no artifact. A symlinked directory that resolves inside the root is not followed either, and earns no warning: its content is read once, under its real path. - A scan root that cannot be listed is not an empty product.
observation-coverage.jsonreadsindeterminate,scan-warnings.jsoncarriescoverage_indeterminate, and the summary names the root, says coverage is unknown, and closes withFix:instead ofNext:. The exit code is unchanged (warn, never refuse);--strict=coverage_indeterminatemakes such a run fail.
Monorepos and workspaces#
Release one member of a workspace or multi-module repository in one of three ways. Each is supported; the run records which one it was.
- Scan from the workspace root when one lockfile pins every member. npm, yarn and pnpm workspaces, Cargo workspaces, uv workspaces and Dart pub workspaces keep a single lockfile at the workspace root and none in the members.
sbomflow analyze .at that root reads it and records every member's resolved dependencies, attributed to no member: a root run inventories the whole workspace, and SBOMFlow never guesses which service a dependency belongs to. - Scan one member by pointing at its directory (
sbomflow analyze services/a). The walk never leaves the scan root, so the lockfile at the workspace root is not read. When the member declares dependencies of an ecosystem that no lockfile inside the scan root covers, and a lockfile of that ecosystem sits between the scan root and the repository root, the run says so with thelockfile_above_scan_rootwarning, naming the lockfile by its path relative to the scan root (../../package-lock.json). The inventory is then partial for that ecosystem: the member's declared ranges are recorded and the versions the lockfile resolves are not. Whether that lockfile pins the member is not determined — the run never opens it — so a directory that is an independent project below a lockfile-holding directory gets the same warning, and a reviewer can accept it there. - Give the member its own lockfile, and a per-member run is complete on its own terms: no warning, and the scope below is still recorded.
What the run records about its scope. When the scan root lies below its repository's root, release-record.json carries scan_scope: subtree (the scan root relative to the repository root, POSIX form, e.g. services/a, with subtree_relative_to: repository_root), repository_root_levels_above_scan_root, and lockfiles_above_scan_root — one row per lockfile the warning names, with path, family, levels_above_scan_root, manifests_without_a_lockfile_in_scope and read_by_this_run: false. Which files the run parsed is already recorded per component (source_files) and per input (artifacts in evidence-pack.json). scan_scope is written into the release record only, never into the evidence pack, so it does not move the evidence digest an approval binds to. A run whose scan root IS its repository's root writes no scan_scope key and its record is the one it always wrote; so does a run for which no repository root was found.
Why the subtree is safe to record. An absolute scan root is recorded in target_path as its final component only, so that no artifact publishes the host's directory layout. subtree keeps that promise: it names only directories inside the repository, it is identical on every checkout of the repository, and nothing above the repository root is ever recorded.
How far it looks. The ascent walks the scan root's parents as the path was given (a symlinked scan root is not resolved) and stops at the first directory holding .git or .hg (a .git directory in a clone, a .git file in a worktree), or after WORKSPACE_ASCENT_MAX_LEVELS (8) levels. Above the scan root it only lstats named entries: no file there is opened, no symlink is followed, a directory named like a lockfile is not a lockfile, and an entry it cannot examine stops the ascent. Without a repository root within 8 levels nothing above the scan root is looked for at all, so a per-member scan of an unpacked archive is not warned about: scan such a tree from its workspace root.
Which lockfiles and manifests. Derived from the lockfile parsers in the first table and the manifest rows of the same ecosystem families, never listed by hand. go.mod is itself a parsed lockfile (its requirements are exact versions), so a Go module is never declared without a lock, and go.work is not a parsed input. A lockfile whose family has no manifest row in the catalog is not looked for, because nothing in the scanned tree could be declared without it: bun.lock, deno.lock, dependencies.lock, go.mod, go.sum, packages.config, packages.lock.json, project.assets.json, renv.lock. Among them, a Bun or Deno workspace member (whose package.json or deno.json is catalogued under another family, or not at all) is not reported yet.
| Ecosystem family | Manifests in the scanned tree | Lockfiles looked for above the scan root |
|---|---|---|
| cargo | Cargo.toml | Cargo.lock |
| cocoapods | Podfile | Podfile.lock |
| composer | composer.json | composer.lock |
| conan | conanfile.py, conanfile.txt | conan.lock |
| helm | Chart.yaml | Chart.lock |
| hex | mix.exs | mix.lock, rebar.lock |
| maven | build.gradle, build.gradle.kts, verification-metadata.xml | gradle.lockfile |
| nix | default.nix, flake.nix | flake.lock |
| npm | package.json | npm-shrinkwrap.json, package-lock.json, pnpm-lock.yaml, yarn.lock |
| perl | cpanfile | cpanfile.snapshot |
| pub | pubspec.yaml | pubspec.lock |
| python | constraints.txt, requirements.txt, Pipfile, pyproject.toml, requirements.txt | Pipfile.lock, poetry.lock, uv.lock |
| rubygems | Gemfile | Gemfile.lock |
| swiftpm | Package.swift | Package.resolved |
What a repeated JSON key does#
JSON lets an object state the same key twice, and a parser keeps the LAST value without a word, so a reader of the file and SBOMFlow could disagree about what it says. Every JSON read SBOMFlow makes is classified, site by site, in a roster derived from the code; a new read with no class fails the build.
- Decisions, trust anchors and records being verified are refused. The gate policy, waivers, reviews and claims read back from a store, match disputes, SSVC context, licence conclusions, a trust policy, entitlements, regime profiles, requirement catalogs, CRA manufacturer inputs,
storeseals and reissue plans, a batch job's network posture, GitHub and tracker responses undersync --apply, and any sealed, stored or handed-over record being verified, replayed or cut into a passport, supplier package or lifecycle-event export. The document is never read with either value: the command stops with the error a malformed document gets there and writes nothing, or, where the document is one input among several, it becomes a named unusable input. - Files found in the scanned tree and third-party tool output are reported unreadable, and the scan continues. The input's own unreadable or malformed warning names the file and the repeated key.
- Imported SBOMs, supplier VEX, external scanner reports, the AI manifest,
--vulnerability-reviews, the product config, and KEV, NVD and EPSS data keep the last value and warn.duplicate_json_key(duplicate_config_keyfor the config) names the file, the JSON path and the key; nothing is changed or suppressed. A later verification that replays those reviews refuses them, because it cannot say which of the two it vouched for. A staged feed counts a record that repeats a key as non-conformant and still imports it; a repeat in the feed's wrapper, which could discard a whole list of records, refuses it. - Files this run wrote a moment earlier, data shipped inside the package, and reads of key names only are not re-checked. The packaged files are proven free of repeated keys, and an object's key names are the same whichever repeated value wins.
- Not covered, by design: a file the scan did not recognise is sampled for worklist signals, and those samples are never echoed into a warning, so a repeated key there is not named.
Compared by digest when sbomflow.yaml names them#
covered_software: names files of the release tree by path, each with the SHA-256 you recorded for it (reference_sha256) from the record that identifies it. These files are not new scan inputs: each is hashed and compared with its recorded digest, and nothing is parsed from it. The path is relative to the tree analyze scans; an absolute path, a host path, or a .. segment refuses the config. A symbolic link anywhere on the path is never followed and reads path_not_regular_file. The result is covered-software.json: identical means the bytes carry the recorded digest, and SBOMFlow reads no scheme rule and decides nothing about re-certification.
Findings from an assessment report (--assessment-findings)#
analyze and audit read one local file named by --assessment-findings PATH, never discovered by the scan: the findings an assessment report listed (a penetration test, a lab evaluation, a process audit, a bug-bounty programme; any assessor), restated by you. The file is {"schema_version": "sbomflow-assessment-findings-v1", "source": {"id", "report_sha256"}, "findings": [...]}, each finding {id, title, severity_as_supplied, component_hint?, first_reported_version?}; its published JSON Schema is listed by sbomflow schema list. The source.id and each finding id are 1 to 64 letters, digits, dot, underscore or hyphen, because they form the finding's review key assessment:<source id>:<finding id>; text is bounded (title 512, severity_as_supplied 128, component_hint 256, first_reported_version 128 characters). The report itself is never read: its digest is looked up among the preserved artifacts the run declares. A file that cannot be read refuses the run with E015; one that is read and is not such a document (not JSON, a repeated JSON key, an unknown top-level or source key, a malformed source id or digest, findings not a list) refuses it with E016. An entry that is not a well-formed finding is skipped and named (assessment_findings_malformed), never repaired. The result is assessment-findings-ledger.json; see outputs.
Per-component support files named by sbomflow.yaml#
component_support.declarations names local JSON files, each relative to the directory of sbomflow.yaml. They are not scan inputs: nothing in the release tree is read for them. Each file (schema_version: sbomflow-component-support-declaration-v1) lists entries that name one component by identifier (a Package URL, or a CPE) with a support_level (actively_maintained, no_longer_maintained or abandoned), an optional support_ends date and an optional note. A declaration matches by identifier equality only; nothing is inferred from registry metadata, dates or names. The result is component-support.json, with a row for every component: not_declared when nobody declared one, and undetermined with the declared value kept when a level or date cannot be read.
component_support.snapshots names local lifecycle snapshots, also relative to sbomflow.yaml and also never scan inputs: an operator snapshot (schema_version: sbomflow-component-support-snapshot-v1, entries of {identifier, cycle, support_ends, source_url, retrieved}) or a public lifecycle API's product document saved locally (schema 1.x; its generated_at, result.identifiers of type purl or cpe, result.links.html and each release's name, eolFrom and isEol are read, nothing else). The run fetches nothing; sbomflow component-support fetch --product <name> --output <dir> is the separate, explicit network step that saves such documents with a manifest of their URL, retrieval time, SHA-256 and the source's licence notice. Each component's lifecycle_snapshot reads maintained, eol, not_mapped or unknown, and is never read from its declared level.
Devices named in identity.devices#
Industrial, energy and building-automation advisories name a device by vendor, product name, model number and firmware range, almost never by a purl. To see what the CSAF advisories you already hand to a run (supplier_vex: or --supplier-vex) state about a device you ship or integrate, declare it, spelled exactly as the advisories spell it:
identity:
devices:
- id: rtu-main # lowercase letters, digits, . _ -; unique
vendor: "Example Controls" # or a list of the spellings advisories use
model_numbers: ["EC-100-2A"] # the concrete model; no ? * or \
firmware_version: "4.2.1" # as advisories name it; never product.version
- id: gateway-module
vendor: ["Example Controls", "Example Controls AG"]
product_name: "EC-200 Gateway"
firmware_version: "V2.012"
relates_to: product # or the purl of a component of this runEach entry needs id, vendor, firmware_version and at least one of product_name or model_numbers. Values are kept verbatim: no case folding, no Unicode normalisation, no v stripping. An unknown key, a repeated id, an empty value, surrounding whitespace or a line break, a repeated list entry, or a declared model number holding ?, * or \ refuses the config (E010); it is never repaired. The key is file-only. The result is device-advisory-context.json: observations for a person to read, never findings; see outputs.
Package lists embedded in binaries (opt-in)#
With binary_inventory.enabled and binary_inventory.read_embedded_package_metadata both true, each binary the inventory selected (ELF, PE or thin Mach-O) is also read for the module list its toolchain embedded: Go build info (.go.buildinfo, __go_buildinfo, or the first read/write data section of a PE file) and cargo-auditable's zlib-compressed .dep-v0 JSON. Each declared module becomes a pkg:golang or pkg:cargo component, the Go toolchain pkg:golang/stdlib, each with a binary_embedded_metadata record naming the binary, its SHA-256 and the section. What the binary declares is recorded, never verified. A region that is malformed (binary_buildinfo_malformed) or over a cap (binary_buildinfo_truncated) yields no component from that binary; a universal Mach-O file is not read.
Firmware blobs listed in linux-firmware's WHENCE (opt-in)#
With binary_inventory.enabled, a firmware blob under a lib/firmware/ directory is inventoried by its content hash: no purl, no version, licence NOASSERTION. SBOMFlow also reads the WHENCE index linux-firmware ships, from a lib/firmware/WHENCE inside the scanned tree or, for a lib/firmware directory with none of its own, from the file binary_inventory.firmware_whence names, and records per blob whether the index lists it, as a firmware_whence row on the blob's evidence-pack component. Only the File:, RawFile: and Link: lines are read, as linux-firmware's own install script reads them (basis: source code). License:, Driver: and Version: lines are not read, so a listing never states the terms a blob may ship under, and no purl, version or licence is added. A WHENCE too large to read whole is refused with a warning and yields no rows, so a failed read never makes a blob look unlisted.
Read for declared identity in a preserved original (36)#
These are not scan inputs. When a preserved artifact's original is a file in one of these formats, its own statements about itself are read under the cited published specification and recorded as file_declared_identity — never verified, never a finding, and never read past the identity the specification names. See Runtime and test evidence. The fourth column names the field whose value is a GNU build id; only that field is compared with the build ids of the release's declared firmware images (build_id_match), and no other declared value is ever matched or verified. The last column names the field whose value is the version the file declares about the build it came from; a release run sets it beside the product version the run states (declared_version_context: agree, differ or not_comparable, exact equality after trimming), as context only — never a match, a finding, a warning or a gate input. A name marked "read only when the format's marker is at offset N" is no claim: any other file under it is treated as if no reader were registered for it.
| Format | Selected by | Specification cited | Build id compared with the release's images | Declared version set beside the release version |
|---|---|---|---|---|
| sarif | .sarif, .sarif.json | Static Analysis Results Interchange Format (SARIF) Version 2.1.0 Plus Errata 01, 2.1.0 plus Errata 01 | no | no |
| pcapng | *.pcapng | PCAP Now Generic (pcapng) Capture File Format, draft-ietf-opsawg-pcapng-06 | no | no |
| elf-package-note | .elf, .so, .axf, .out | UAPI.8 Package Metadata for Executable Files, 1.0 | no | no |
| ctf1-metadata | .ctf, .ctf-metadata, metadata | Common Trace Format v1.8.3, 1.8.3 | no | no |
| ctf2-metadata | .ctf2, .ctf2-metadata, metadata | CTF2-SPEC-2.0: Common Trace Format version 2, CTF2-SPEC-2.0 | no | no |
| perf-data | .perf-data, .perf.data, perf.data | perf.data format, Linux v6.12 (the document states: Uptodate as of v4.7) | build_id | no |
| android-bugreport | .bugreport-zip, .bugreport.zip, bugreport-*.zip | Bugreport file format, android-15.0.0_r1 | no | no |
| afl-fuzzer-stats | .fuzzer-stats, .fuzzer_stats, fuzzer_stats | The afl-fuzz approach (AFL++ documentation), v5.03c | no | no |
| lcov-tracefile | *.info | geninfo(1), section TRACEFILE FORMAT (LCOV docs/man/geninfo.rst), v2.5 | no | no |
| zephyr-coredump | *.zephyr-coredump, coredump.bin (a name other formats share) | Zephyr core dump, section File Format (doc/services/debugging/coredump.rst), v4.4.2 (commit dccb09599635bdff17633fa7e9dab014b91dce90; document sha256 da85e28c77969204dd7e4a46016af6818ec0f20e43cdc0db267788d7d36b42f6) | no | no |
| zephyr-coredump-log | *.zephyr-coredump-log, coredump.log (a name other formats share) | Zephyr core dump printed by the logging backend (coredump_serial_log_parser.py), v4.4.2 (commit dccb09599635bdff17633fa7e9dab014b91dce90): scripts/coredump/coredump_serial_log_parser.py sha256 4d05eb85ce73a4f791e529ab671c0ddf9903fa86f3d0112e474678cc1a596fd6, include/zephyr/debug/coredump.h sha256 bdfb3571ba1ceff18704c97ec508499157465feda682a8248777661c3df1af45, subsys/debug/coredump/coredump_backend_logging.c sha256 be1cba8afc8e728fc499263a0ccf2700b6a163977b8948cf38ecab5317ba3c4a, subsys/debug/coredump/Kconfig sha256 15b2821902fbb4170581f682c3517a1c4c5d38123d095d8a1c0da87335506205 (the logging backend is the default); the file header as doc/services/debugging/coredump.rst sha256 da85e28c77969204dd7e4a46016af6818ec0f20e43cdc0db267788d7d36b42f6 specifies it; basis: source code at dccb09599635bdff17633fa7e9dab014b91dce90 (scripts/coredump/coredump_serial_log_parser.py, Apache-2.0, sha256 4d05eb85ce73a4f791e529ab671c0ddf9903fa86f3d0112e474678cc1a596fd6) | no | no |
| crashcatcher-dump | .crashcatcher, cc_coredump.dmp, .dmp (a name other formats share) | CrashCatcher README, section Dump Format (README.creole), commit 0222f9d3cf07cd9c327a4a7577efd5c1424a55f7 (the repository has no tags; document sha256 9a43e4b40d056ff378396d5f6b20601a13b2a0626166dee68ab6843a0aaa12e8) | no | no |
| memfault-coredump | *.memfault-coredump | Coredump Collection, section Memfault Coredump Format (Memfault Docs, MCU), page "Last updated on Jul 23, 2026" (page sha256 335d49a0a096a02ca2224956bd5e9c1d025e01e947b20f7ec2f236a6aaa801d3); block type codes derived from the documented order of the type list and its example 0x01 (Memory Region), not stated per type | no | software_version |
| elf-core | .core (a name other formats share), core (a name other formats share), core.[0-9] (a name other formats share), vmcore (a name other formats share) | elf(5), Linux manual page (ELF header, program header and note header), with the System V gABI chapter 4 ELF Header and chapter 5 Program Header for the numbers ET_CORE, e_machine and PT_NOTE, elf(5) copy sha256 da01af39213c299f91b20efbbf57b2b53bf4c41cd97d707df9182a25f2a4c345; gABI ch4 https://www.sco.com/developers/gabi/latest/ch4.eheader.html sha256 7b2d4920ce3dd63ab754427d52fe2eaea7f693080b2151979ac0af89a7c9c088; gABI ch5 https://www.sco.com/developers/gabi/latest/ch5.pheader.html sha256 656798000adc23608001017f3c126303734a441eb6b400474125ba66cfc223b9. The gABI ch5 text states "In 64-bit objects (files with e_ident[EI_CLASS] equal to ELFCLASS64), each entry is an array of 8-byte words in the format of the target processor." This reader does not follow it: it walks the note header elf(5) defines (Elf64_Nhdr is three 4-byte words, and the descriptor "has a 4 byte alignment"), because that manual page defines the layout Linux cores are written in | no | no |
| esp-core-dump-image | *.bin (any such file, read only when the format's marker is found within its first 28 bytes of a file carrying 0x01 at offset 5, whose length word at offset 0 fits the file) | ESP-IDF core-dump image: core_dump_header_t, the data and its checksum (esp-coredump loader.py), commit d54b4a611c34efbc75cae1f862f58097f909261c: esp_coredump/corefile/loader.py sha256 0b6f9d838b109ff73e2c145d30231562321452e5ddfe913359209e39f452e795; the writer's header per generation: ESP-IDF v4.4 (8153bfe4125e6a608abccf1561fd10285016c90a) components/espcoredump/include_core_dump/esp_core_dump_priv.h sha256 d51292315b9da48acbafe064bcaa9f6174cc52a451c2e48213a74a3dd3f5c121, ESP-IDF v5.3 (e0991facf5ecb362af6aac1fae972139eb38d2e4) components/espcoredump/include_core_dump/esp_core_dump_types.h sha256 5674f7f769499e9499bf5abd3c6454998125d743a3fd479999e8ea09716939d2, ESP-IDF 4d59230ddff16327812782151ef0afef202dc6d7 components/espcoredump/include_core_dump/esp_core_dump_types.h sha256 f79c7ecb73a70b44ba7ac6f4a4939ab61c75549383bce2056edcac86f3082488; basis: source code at d54b4a611c34efbc75cae1f862f58097f909261c (esp_coredump/corefile/loader.py, Apache-2.0, sha256 0b6f9d838b109ff73e2c145d30231562321452e5ddfe913359209e39f452e795) | no | no |
| minidump | .mdmp, .dmp (a name other formats share) | minidump_format.h (Google Breakpad) for MD_HEADER_SIGNATURE, MD_HEADER_VERSION, MDString, MDVSFixedFileInfo, MD_MODULE_SIZE and the CodeView layouts MDCVInfoPDB70, MDCVInfoPDB20 and MDCVInfoELF, with the minidumpapiset.h reference (learn.microsoft.com) for MINIDUMP_HEADER, MINIDUMP_DIRECTORY, MINIDUMP_LOCATION_DESCRIPTOR, MINIDUMP_STREAM_TYPE, MINIDUMP_MODULE_LIST and MINIDUMP_MODULE, header at commit 868abe6f016cfeabfb7208681e89031ae667c336 (sha256 6e88e2f06e4fe60b8a3dee7f1e39e001c799f69ac3f244d3e36295c38c834c3c); reference pages under https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ read as saved copies: minidump_header sha256 07022e2ff2ecc3b437e52fd8797a150ac01c2e2daa3e7cfbe5a99651969d511f, minidump_directory 01abd24bc068075ee124b85f0f6a8d4b7f07ef41a9b4838c0551daa341939bed, minidump_location_descriptor 49cf1d0e7c009735e147bd1840c4c11c0406a5c7ad278725fed66567df692641, minidump_stream_type ca18ca69ed79d5a5b0f6dab75753a4ed1cb83610303606e30269e152f048d654, minidump_module_list 50349711c9df18f7be0078653d615f61a16a79d38993bae3ef73ee9ca4f57004, minidump_module af76df812069003e77225d851db2c061c8d37d2de7a69b5b857c7a79e483c822. The reference does not state the signature or version values, the string or fixed-file-information layouts, or the CodeView record's layout; the header's CodeView layouts are read at that commit (MDGUID lines 80-85, MDCVInfoPDB20 459-464 and signature 469, MDCVInfoPDB70 471-477 and signature 482, MDCVInfoELF 492-497 and signature 502), identity fields only: a GUID, an age, a build id, and a PDB file name without its directories; no record's bytes are recorded; basis: source code at 868abe6f016cfeabfb7208681e89031ae667c336 (src/google_breakpad/common/minidump_format.h, BSD-3-Clause, sha256 6e88e2f06e4fe60b8a3dee7f1e39e001c799f69ac3f244d3e36295c38c834c3c) | no | no |
| intel-hex | .ihex, .ihx, *.hex (a name other formats share) | Hexadecimal Object File Format Specification (Intel), Revision A, January 6, 1988 (copy read: sha256 7afb47d45521a0dc91a1ab1b91b2f507d0a9b64850c7d6b4998a3fe99127cd8a) | no | no |
| motorola-srec | .srec, .s19, .s28, .s37, *.mot | M68000 Family Programmer's Reference Manual (Motorola), Appendix C S-Record Output Format, Motorola Inc., 1992; Appendix C is PDF pages 641-644 (copy read: sha256 06e4864b78da0e815054cead9326b7ec9914661f240fd39a455f2061ff47c4e8) | no | no |
| uf2 | *.uf2 | USB Flashing Format (UF2), README.md sections File format, Flags and Family ID, commit 90e9741f217f5a40c98ba74d663e408041037578 (README sha256 61dda8a7a1b8ff6a576fd9d5df003356b0e71d2450e59a5823cf426c4378ff17) | no | no |
| dfm-alert | *.dfm-alert | dfmEntry.c (Percepio DFM v2.1.0) for DfmEntryHeader_t, the entry markers, footer, version and types, with include/dfmAlert.h for DfmAlert_t, DFM v2.1.0 at commit c3055e4b6ae5627407b002e200f769596b7cfe01: DFM/dfmEntry.c sha256 aab4b74bb2b09f419458699e4355c0281cb1982117fa1bc61457ca2ff8071ee6 (lines 16, 18-33, 47-50, 82-123, 186-230 and 561; byte-identical in percepio/demos at commit cfae6c6a7d4fae38d527200754c326baf7a04cde; its layout comment at lines 237-241 omits the device name, which the code writes between the session id and the description at lines 205-216, and the code is followed); DFM/include/dfmAlert.h sha256 67dd2a2f240f07a15e6e4102deddc2db50887405ab32159bd0a3048f333eef96 (lines 87-114, DfmAlert_t); DFM/dfmAlert.c sha256 939889cc7905e04fa9429e548aec1873d141ee6dd71be0194c6e5acc949b1249 (lines 594-620 and 982-988, whose checksum function returns 0, so the checksum is not verified); DFM/include/dfmTypes.h sha256 602d59bb73424a8c9016bb69b8aed5216fd104ef8d0f407ee74cc225689e38b9 (lines 31-33); DFM/include/dfm.h sha256 9908fe5f0681f0cbd75647433c223d839d501aeede20a02a97559a5e7c536422 (lines 147-151, DFM_VERSION 3). The source states field order and types, not offsets: the offsets are derived from them and equal the compiler's offsetof in a host build of the pinned code; basis: source code at c3055e4b6ae5627407b002e200f769596b7cfe01 (DFM/dfmEntry.c, Apache-2.0, sha256 aab4b74bb2b09f419458699e4355c0281cb1982117fa1bc61457ca2ff8071ee6) | no | firmware_version |
| dfm-alert-serial-capture | *.dfm-alert-log | cloudports/Serial/dfmCloudPort.c (Percepio DFM v2.1.0) for the console framing, with dfmEntry.c and include/dfmAlert.h for the entries it frames, DFM v2.1.0 at commit c3055e4b6ae5627407b002e200f769596b7cfe01: DFM/cloudports/Serial/dfmCloudPort.c sha256 5e5d00ed4888d1b8ea4555c719090c5383ce35ecb18fb527ad5b6edf0043a6d1 (lines 31-108: one block per entry, at most 20 bytes per line as %02X, an entry over 0xFFFF bytes refused, Checksum: 0 printed for every entry); the percepio/demos copy at commit cfae6c6a7d4fae38d527200754c326baf7a04cde (sha256 5a39e16eedb0022d006521c87baa570ad158fb7f34e9f60ba3b95b01e8feeb0d) differs only in ending lines with a configurable LNBR, \n or \r\n. Entries: DFM/dfmEntry.c sha256 aab4b74bb2b09f419458699e4355c0281cb1982117fa1bc61457ca2ff8071ee6 (lines 16, 18-33, 47-50, 82-123, 186-230 and 561; byte-identical in percepio/demos at commit cfae6c6a7d4fae38d527200754c326baf7a04cde; its layout comment at lines 237-241 omits the device name, which the code writes between the session id and the description at lines 205-216, and the code is followed); DFM/include/dfmAlert.h sha256 67dd2a2f240f07a15e6e4102deddc2db50887405ab32159bd0a3048f333eef96 (lines 87-114, DfmAlert_t); DFM/dfmAlert.c sha256 939889cc7905e04fa9429e548aec1873d141ee6dd71be0194c6e5acc949b1249 (lines 594-620 and 982-988, whose checksum function returns 0, so the checksum is not verified); DFM/include/dfmTypes.h sha256 602d59bb73424a8c9016bb69b8aed5216fd104ef8d0f407ee74cc225689e38b9 (lines 31-33); DFM/include/dfm.h sha256 9908fe5f0681f0cbd75647433c223d839d501aeede20a02a97559a5e7c536422 (lines 147-151, DFM_VERSION 3). The source states field order and types, not offsets: the offsets are derived from them and equal the compiler's offsetof in a host build of the pinned code; basis: source code at c3055e4b6ae5627407b002e200f769596b7cfe01 (DFM/cloudports/Serial/dfmCloudPort.c, Apache-2.0, sha256 5e5d00ed4888d1b8ea4555c719090c5383ce35ecb18fb527ad5b6edf0043a6d1) | no | firmware_version |
| tracerecorder-psf | trace.psf, *.psf (a name other formats share) | trcStreamingRecorder.c (TraceRecorder) for the TraceHeader struct, TRACE_FORMAT_VERSION, TRACE_PSF_ENDIANESS_IDENTIFIER and how each header field is filled, with include/trcRecorder.h for TRC_PLATFORM_CFG_LENGTH and TRC_HEADER_BUFFER_SIZE and each kernel port's TRACE_KERNEL_VERSION, TraceRecorder v4.12.0 at commit c3055e4b6ae5627407b002e200f769596b7cfe01 (trcStreamingRecorder.c sha256 b192aa2af301a3e8a2ea5a682e3bc5d9872c594df60919156cee3171f4d8062f, lines 24-36, 55-59 and 313-347; the same lines in the standalone TraceRecorderSource v4.11.0, commit 2f888cb9e6240c88e33eacd5acd50555fb13fbf5); include/trcRecorder.h sha256 24611583c7e966b86f492e1dbd7b1070b141b281fba3bca2fe58fd600b420859 (lines 70 and 73); include/trcHardwarePort.h sha256 8fdb4d3210cf7025330550c0f041ac5a73c2076a2ec30f4acc01d49b4b7eecf0 (TRC_IRQ_PRIORITY_ORDER); kernelports trcKernelPort.h for FreeRTOS sha256 a8a2745531327c01a468064f971555532d4cc44110025e4fcd80d20b0f5a20ea, ESP-IDF FreeRTOS 004ac83163074a276adcd1567cec2ca0ee6289c26551f5e91ccf9f8d55df3e47, BareMetal 6db7c5e491bfbcf5dc0b7d2774c735f5b44a93165559fd0db2ab29a3331bb749, ThreadX 76f56ec7fb34a2c96d75ffbdf4de671396b82a349d1605c16e7e2ae42a8bc31c, Zephyr 3069fa8128b1b5b5f91dfe518b5a6d465916d605053f0537ed9b8032536149f1. The source states field order and types, not offsets: the offsets are derived from them (every field falls on a multiple of its own size, so there is no padding, and the fields sum to the 32-byte TRC_HEADER_BUFFER_SIZE). After the header, only in a one-core recording and only when the start event follows the entries: trcStreamingRecorder.c lines 539-542 and 571-627 (what is written after the header, in order); include/trcTimestamp.h sha256 5217d437c676fbf6042022c024cc2f097375aa76733ff97aac3d87d127ecd031 (lines 35-44, the timestamp block); include/trcEntryTable.h sha256 ff22170fbfd3acc57a9a7082e3d019b749ff3c49a08a35d989f5c199e6f00e40 (lines 43-81, the entry and its symbol size); include/trcDefines.h sha256 cd32b057e16aff20738a3345b5a9614d331487668071a702ba887cdf221909f1 (lines 71-81, the entry option bits); trcExtension.c sha256 944f1122da4f3a3554c09d6a206918e9a3ddd3b6fe6a731d129e33a0df710732 (lines 17-21 and 41-79, an extension's name and version); trcEvent.c sha256 c3dc8ea5f235a7e0e24db47741d5e0e7776d2436e821e01da7d9f4f1fcadceae (line 44 and lines 278-299, the event id and the raw writes' alignment); include/trcTypes.h sha256 5cf0e7ea33cd9641992291a39497cfedfb21814d672cfc0e43a949ec13af99fd (lines 22-28, the base type); kernelports/ThreadX/trcCTI.c sha256 e5c738fac3bef96c0e36b335724e33cfcb9309e338560c7b2d879283263f0c48 (lines 1562-1584, why a ThreadX recording is not read past its header). Entry names other than an extension's are never read; basis: source code at c3055e4b6ae5627407b002e200f769596b7cfe01 (TraceRecorder/trcStreamingRecorder.c, Apache-2.0, sha256 b192aa2af301a3e8a2ea5a682e3bc5d9872c594df60919156cee3171f4d8062f) | no | no |
| tracerecorder-ringbuffer | *.bin (any such file, read only when the format's marker is at offset 4) | trcStreamPort.h (TraceRecorder RingBuffer stream port) for TraceRingBuffer_t, with trcStreamPort.c for its start and end markers and the streaming header inside it, TraceRecorder v4.12.0 at commit c3055e4b6ae5627407b002e200f769596b7cfe01: trcStreamPort.h sha256 58ef02c658f522365e22b2aea3f0df0839152d5bfa6815d82a6cdae07dd68758 (lines 55-59 TraceMultiCoreBuffer_t, 64-74 TraceRingBuffer_t, 79-83 TraceStreamPortBuffer_t); streamports/RingBuffer/trcStreamPort.c sha256 019b11c671f25760a35c9cd2b005bfbe4b7ce6ce953fffcf7531b8d233f6bbde (lines 18-19 and 34 RecorderDataPtr, 36 uxSize, 65-78 END_MARKERS, 80-93 START_MARKERS); the header inside it under trcStreamingRecorder.c sha256 b192aa2af301a3e8a2ea5a682e3bc5d9872c594df60919156cee3171f4d8062f, as for the streaming trace; include/trcTimestamp.h sha256 5217d437c676fbf6042022c024cc2f097375aa76733ff97aac3d87d127ecd031 (lines 35-44); include/trcEntryTable.h sha256 ff22170fbfd3acc57a9a7082e3d019b749ff3c49a08a35d989f5c199e6f00e40 (lines 51-81, TRC_ENTRY_TABLE_STATE_COUNT 3); trcEntryTable.c sha256 18c204977c9cf5b946aec3b30083dd743e611f62a088160c175b890e2f7f80e8 (lines 59-61); include/trcMultiCoreEventBuffer.h sha256 8e9cf450ddd9cd00ec69d17ef2377f63572708551942962a6a12a5de87ad501c (lines 35-38). The markers and the header sit at fixed offsets 4 and 16 of the ring buffer. The compiler put them there on a 64-bit host and on 32-bit little- and big-endian ARM targets, measured by a host harness over the pinned code. The end markers' offset is derived from sizes the file declares, and the derivation assumes the target's pointers are as wide as its TraceUnsignedBaseType_t, which the file does not declare; basis: source code at c3055e4b6ae5627407b002e200f769596b7cfe01 (TraceRecorder/streamports/RingBuffer/include/trcStreamPort.h, Apache-2.0, sha256 58ef02c658f522365e22b2aea3f0df0839152d5bfa6815d82a6cdae07dd68758) | no | no |
| esp-app-image | *.bin (any such file, read only when the format's marker is at offset 32 of a file opening with 0xE9) | ESP-IDF application image: esp_app_desc_t (esp_app_desc.h) at the fixed App Image Format offset, commit 4d59230ddff16327812782151ef0afef202dc6d7: components/esp_app_format/include/esp_app_desc.h sha256 452c93fdd0c1dfe6396cee13f5d95d71ab304bdd4565d696d80d76a2e269a6b0; basis: source code at 4d59230ddff16327812782151ef0afef202dc6d7 (components/esp_app_format/include/esp_app_desc.h, Apache-2.0, sha256 452c93fdd0c1dfe6396cee13f5d95d71ab304bdd4565d696d80d76a2e269a6b0) | no | esp_app_version |
| coresight-snapshot | snapshot.ini (a name other formats share) | Debug and Trace Snapshot File Format (Arm document ARM-ECM-0611873), 0.2, 24/10/2016 (the copy OpenCSD distributes at commit 59f15320637ce6e510604e7bed550d7ad109d15d; document sha256 7ec9ba1b56943dc8af44a1f4d4ac47e43f8dc2740c75237d40d1d1e730704a04) | no | no |
| coresight-snapshot-trace-metadata | trace.ini (a name other formats share) | Debug and Trace Snapshot File Format (Arm document ARM-ECM-0611873), 0.2, 24/10/2016 (the copy OpenCSD distributes at commit 59f15320637ce6e510604e7bed550d7ad109d15d; document sha256 7ec9ba1b56943dc8af44a1f4d4ac47e43f8dc2740c75237d40d1d1e730704a04) | no | no |
| coresight-snapshot-device | *.ini (any such file, read only when the format's marker is found within its first 4096 bytes) | Debug and Trace Snapshot File Format (Arm document ARM-ECM-0611873), 0.2, 24/10/2016 (the copy OpenCSD distributes at commit 59f15320637ce6e510604e7bed550d7ad109d15d; document sha256 7ec9ba1b56943dc8af44a1f4d4ac47e43f8dc2740c75237d40d1d1e730704a04) | no | no |
| tracerecorder-streamport-buffer | dfm_trace.psfs, *.psfs (a name other formats share) | trcStreamPort.h (TraceRecorder RingBuffer stream port) for TraceStreamPortBuffer_t, the buffer xTraceGetEventBuffer() returns and the DFM library attaches as dfm_trace.psfs, TraceRecorder v4.12.0 at commit c3055e4b6ae5627407b002e200f769596b7cfe01: trcStreamingRecorder.c lines 438-450 (xTraceGetEventBuffer returns xStreamPortBuffer and its size); DFM/dfmCrashCatcher.c sha256 221b60ef95fe6aef029d30b05722a1b6817b2941add854c023feb1e4a8b04eb0 (lines 181-195, the payload name dfm_trace.psfs in streaming mode); trcStreamPort.h sha256 58ef02c658f522365e22b2aea3f0df0839152d5bfa6815d82a6cdae07dd68758 (lines 55-59 TraceMultiCoreBuffer_t, 64-74 TraceRingBuffer_t, 79-83 TraceStreamPortBuffer_t); streamports/RingBuffer/trcStreamPort.c sha256 019b11c671f25760a35c9cd2b005bfbe4b7ce6ce953fffcf7531b8d233f6bbde (lines 18-19 and 34 RecorderDataPtr, 36 uxSize, 65-78 END_MARKERS, 80-93 START_MARKERS); the header inside it under trcStreamingRecorder.c sha256 b192aa2af301a3e8a2ea5a682e3bc5d9872c594df60919156cee3171f4d8062f, as for the streaming trace; include/trcTimestamp.h sha256 5217d437c676fbf6042022c024cc2f097375aa76733ff97aac3d87d127ecd031 (lines 35-44); include/trcEntryTable.h sha256 ff22170fbfd3acc57a9a7082e3d019b749ff3c49a08a35d989f5c199e6f00e40 (lines 51-81, TRC_ENTRY_TABLE_STATE_COUNT 3); trcEntryTable.c sha256 18c204977c9cf5b946aec3b30083dd743e611f62a088160c175b890e2f7f80e8 (lines 59-61); include/trcMultiCoreEventBuffer.h sha256 8e9cf450ddd9cd00ec69d17ef2377f63572708551942962a6a12a5de87ad501c (lines 35-38). The markers and the header sit at fixed offsets 4 and 16 of the ring buffer. The compiler put them there on a 64-bit host and on 32-bit little- and big-endian ARM targets, measured by a host harness over the pinned code. The end markers' offset is derived from sizes the file declares, and the derivation assumes the target's pointers are as wide as its TraceUnsignedBaseType_t, which the file does not declare. The ring buffer follows TRC_CFG_CORE_COUNT event-buffer pointers, a count the file declares only inside the header, so its position is searched for (from offset 4 at 4-byte steps, within the first 1040 bytes). The position found is then held against the declared core count, and refused if the two disagree; basis: source code at c3055e4b6ae5627407b002e200f769596b7cfe01 (TraceRecorder/streamports/RingBuffer/include/trcStreamPort.h, Apache-2.0, sha256 58ef02c658f522365e22b2aea3f0df0839152d5bfa6815d82a6cdae07dd68758) | no | no |
| tracerecorder-legacy-snapshot | dfm_trace.trc, *.bin (any such file, read only when the format's marker is at offset 0) | trcRecorder.h (TraceRecorder v4.10.3) for RecorderDataType, "the main data structure, read by Tracealyzer from the RAM dump", with trcSnapshotRecorder.c for how its fixed head and markers are filled, TraceRecorderSource tag Tz4/4.10/v4.10.3 at commit 225720467bd286267377d588e8581dc337abc4c8 (the last release with snapshot mode; trcSnapshotRecorder.c is absent from v4.11.0): include/trcRecorder.h sha256 0b46b376448eea5dfdc9aafe34b02a85e4a47e17acf7c823e0ad848d6ada3aa7 (lines 1395-1532); trcSnapshotRecorder.c sha256 dc89395d373567def6ac019e54d887325ae4737001792487d8a849bc94c727b4 (line 30 TRACE_MINOR_VERSION 7, lines 1687-1693 the fixed head, 1708-1719 and 1745-1756 the markers); kernelports/FreeRTOS/include/trcKernelPort.h sha256 97c3e75311000a04a98d14c83a19ba080e014c4c1e9a04ed6b336f1ca8415c34 (line 344 TRACE_KERNEL_VERSION 0x1AA1; at this tag no other kernel port defines snapshot mode). The fields read sit before the first configuration-sized member, and the compiler put them at the same offsets on a 64-bit host and on 32-bit little- and big-endian ARM targets, measured by a host harness over the pinned code; basis: source code at 225720467bd286267377d588e8581dc337abc4c8 (include/trcRecorder.h, Apache-2.0, sha256 0b46b376448eea5dfdc9aafe34b02a85e4a47e17acf7c823e0ad848d6ada3aa7) | no | no |
| px4-ulog | *.ulg | ULog File Format (PX4 Guide, docs/en/dev_log/ulog_file_format.md), PX4-Autopilot commit 7c8d6daca9be7422b328448c6892bd3d55a18521 (document sha256 df1962b4ec9fcd33bc4c989f901add2ecaa84057a7876e080f47a7ca226f8c17); file format version 1 | no | no |
| mcap | *.mcap | MCAP Format Specification (foxglove/mcap website/docs/spec/index.md), commit 3fbb0542becbcba1b203efe0e80debebf0d28f02 (document sha256 cb969b64fb6b7067a18e5d87834ed7784463b050d8f726e4d94bcc51773824c1); major version 0 | no | no |
| rosbag2-metadata | metadata.yaml (a name other formats share) | rosbag2 metadata.yaml as rosbag2_storage writes and decodes it (convert<rosbag2_storage::BagMetadata> in yaml.hpp; BagMetadata in bag_metadata.hpp), commit d51dd4227726cb7cfdcd4a715a6ea97a382a1ec4; yaml.hpp sha256 4cf85d3fe03a2ca6e54bec218d253c2e86b72774e9dc17e3d9e8088a265d0d4a; bag_metadata.hpp sha256 e5a7ba3d945f21862f0e18d521978e18c6a901d84de580f15b58782a1e2ff6d7 (current version 9; versions 1 to 9 decoded); identity fields only; basis: source code at d51dd4227726cb7cfdcd4a715a6ea97a382a1ec4 (rosbag2_storage/include/rosbag2_storage/yaml.hpp, Apache-2.0, sha256 4cf85d3fe03a2ca6e54bec218d253c2e86b72774e9dc17e3d9e8088a265d0d4a) | no | no |
| trace-cmd-dat | trace.dat (a name other formats share), *.dat (any such file, read only when the format's marker is at offset 0) | trace-cmd.dat.v7(5), sections INITIAL FORMAT, FORMAT OF THE SECTION HEADER and OPTIONS SECTION (Documentation/trace-cmd/trace-cmd.dat.v7.5.txt), with trace-cmd.dat.v6(5), section INITIAL FORMAT, for file version 6, trace-cmd tag trace-cmd-v3.4 at commit 3ce20923b3efa60d417da7acc8a327615fbd1419: trace-cmd.dat.v7.5.txt sha256 569d789ed7814d63794cbb33996c62abfab07fb3b7cf54b10919302c7c02929c (lines 21-66 the initial format and compression header, 68-78 the section header, 107-118 the options section, 123-128 DONE, 162-164 UNAME, 178-180 VERSION, 192-194 TRACEID); trace-cmd.dat.v6.5.txt sha256 bc5dcd0ef58df928e88d3f3a116f7a70e16d99d253cd77085289aa2933ec4aaf (lines 21-53 the initial format; line 203, no options defined, so none is read for version 6). The UNAME value's four fields are split as the pinned writer joins them, which the page does not state: tracecmd/trace-record.c sha256 60ffc13ee8020524eea64c8bfc1a43e0d413cb661ddc8830406f246302dae584, add_uname lines 4467-4487 (system name, node name, release, machine); the node name is withheld | no | no |
| perfetto-trace | .perfetto-trace, .pftrace | trace_packet.proto (Perfetto) for TracePacket.system_info, trace_uuid and the compressed packet fields, with trace.proto for Trace.packet, system_info.proto for SystemInfo and Utsname and trace_uuid.proto for TraceUuid, read under the Protocol Buffers encoding guide, Perfetto tag v58.3 at commit 11fbaed836361258f23604daf67c837f3034e663: protos/perfetto/trace/trace_packet.proto sha256 721c51c7cf3efbbadef58805d2217cd9bc7ce216962c8de1d25103bc200999c0 (line 183 trace_uuid = 89, line 193 system_info = 45, lines 257 and 260 compressed_packets = 50 and zstd_compressed_packets = 133); protos/perfetto/trace/trace.proto sha256 e9f9af3a0feb7ed1214aa0e075c50568c1fc4f825d1022b20e0f4df3e17cd264 (line 24 packet = 1); protos/perfetto/common/system_info.proto sha256 210507102e102c3b329be1019c37d28c8eed9c4e7dd5ab7d6106f491b78a1208 (lines 21-26 Utsname sysname 1, version 2, release 3, machine 4; lines 29-31 SystemInfo utsname 1, android_build_fingerprint 2); protos/perfetto/trace/trace_uuid.proto sha256 0324cba70c29628d5e0e5da84bfa5f1915efefbfb9f338406e75afef269c8841 (lines 27-29 TraceUuid msb 1, lsb 2, int64). Wire format: the Protocol Buffers encoding guide, content/programming-guides/encoding.md at protocolbuffers/protocolbuffers.github.io commit c00537c22ece49df397a05586e77af033991ab85 (sha256 ac75150822bf2092c4fcc40b5c687c7c3b6f4d2b45629bc37bb816f7feb05bee): varints, the six wire types, LEN records, two's complement int64 and last-one-wins. Only varints and length-delimited strings are read, so no byte order is assumed; basis: source code at 11fbaed836361258f23604daf67c837f3034e663 (protos/perfetto/trace/trace_packet.proto, Apache-2.0, sha256 721c51c7cf3efbbadef58805d2217cd9bc7ce216962c8de1d25103bc200999c0) | no | no |
| threadx-tracex | *.trx (a name other formats share) | tx_trace.h (Eclipse ThreadX) for TX_TRACE_VALID, the Trace Control Header table and TX_TRACE_HEADER, with TX_TRACE_OBJECT_ENTRY and TX_TRACE_BUFFER_ENTRY for the entry sizes, and tx_trace_enable.c for how the header is filled, ThreadX tag v6.5.1.202602_rel at commit 87ab09cce305eb9cd4aacac4e8c62af72f665bff: common/inc/tx_trace.h sha256 5cced857264b33e3d54fbf9294e8b5911a270ad4ce954211f525040c1747d79e (line 92 TX_TRACE_VALID 0x54585442, lines 110-144 the Trace Control Header table, 149-165 TX_TRACE_HEADER, 171-173 TX_TRACE_OBJECT_REGISTRY_NAME 32, 190-201 TX_TRACE_OBJECT_ENTRY, 348-366 TX_TRACE_BUFFER_ENTRY); common/src/tx_trace_enable.c sha256 b81bb0c9c3c2ca627ff4dcfc2c5f16ef58fef085967996edd563a4cad5c660ca (the header, registry and event area laid end to end, and the reserved words 0x0000, 0xAAAAAAAA, 0xBBBBBBBB and 0xCCCCCCCC). The header carries no version; the reserved words and the pointers' layout are how this reader recognises it. The source states field order and types, not offsets: the offsets are derived from them and equal the compiler's offsetof in a host build of the pinned code and on 32-bit little- and big-endian ARM targets against the pinned Cortex-M3 GNU port; basis: source code at 87ab09cce305eb9cd4aacac4e8c62af72f665bff (common/inc/tx_trace.h, MIT, sha256 5cced857264b33e3d54fbf9294e8b5911a270ad4ce954211f525040c1747d79e) | no | no |
| zephyr-ctf | *.zephyr-ctf | (declares no identity) | no | no |
Attestation predicate types read by provenance-check (5)#
These are not scan inputs: an in-toto statement (plain or in a DSSE envelope) is read only when you pass it to sbomflow provenance-check. Every statement's declared type is recorded verbatim at observed.predicate_type, listed here or not. A type not listed is warned as unsupported_predicate and nothing is extracted from it; a statement with no predicateType takes the legacy shape-detected SLSA path.
| Predicate type | Handling |
|---|---|
https://sbomflow.com/attestation/evidence-bundle@v1 | SBOMFlow's own evidence-bundle statement: warned as unsupported_predicate here, and no build field extracted. |
https://slsa.dev/provenance/v0.2 | SLSA build fields extracted into observed; no level is claimed. |
https://slsa.dev/provenance/v1 | SLSA build fields extracted into observed; no level is claimed. |
https://slsa.dev/verification_summary/v1 | Recorded under verification_summary as the statement of the verifier it names, with the document's digest; SBOMFlow checks nothing in it, and a stated result or level decides nothing. |
https://witness.testifysec.com/attestation-collection/v0.1 | Named at info severity; the collection name and each attestor's type and window recorded under witness_collection; no build field extracted. |
Matching capability by ecosystem#
This section is generated from three code sources and joined so a single lookup answers "for ecosystem X, is a version range advisory-range-evaluated, equality-only, or is there no advisory source at all?" — a question that was previously answerable only by reading the engine's source.
- parsed — the recognized-input catalog above (what a default scan reads).
parsed= a corpus-tested parser;recognized= detected and warned but not parsed yet. - advisory-matchable — the ecosystem-to-advisory (OSV) map and each component's
match_scope.registrymeans a served advisory ecosystem exists to query;noneis an honest statement that no advisory coordinate exists — never a silent miss and never a guessed or cross-ecosystem match. - range-ordering — the validated version-ordering schemes (currently 15).
range-validatedevaluates ranges under a differential-proven ordering for that ecosystem;equality-onlymeans only exact-version equality is decidable (thegenericfallback never fabricates an order).
The vocabulary is fixed — (parsed / recognized / import-by-flag) crossed with (range-validated / equality-only / match_scope: none). There are no support tiers and no scores. Components brought in with an explicit import flag (see Imported by explicit flag above) carry whatever ecosystem the imported record states and are classified by the same two rows below.
Advisory-matchable ecosystems (16)#
A served advisory (OSV) ecosystem exists for these, so a matched component carries match_scope: registry. Every one is also range-validated: the version-ordering work closed the equality-only gap for every matchable ecosystem, so no matchable ecosystem is currently equality-only.
| Internal ecosystem → OSV | Package identity | Recognition | match_scope | Version-range ordering |
|---|---|---|---|---|
apk → Alpine | pkg:apk | parsed | registry | range-validated (apk) |
bioconductor → Bioconductor | pkg:generic (name-matched) | parsed | registry | range-validated (cran) |
cran → CRAN | pkg:cran | parsed | registry | range-validated (cran) |
cargo, crates.io, rust → crates.io | pkg:cargo | parsed | registry | range-validated (semver) |
deb, debian → Debian | pkg:deb | parsed | registry | range-validated (deb) |
go, golang → Go | pkg:golang | parsed | registry | range-validated (semver) |
hex → Hex | pkg:hex | parsed | registry | range-validated (hex) |
linux-kernel → Linux | pkg:generic (name-matched) | parsed | registry | range-validated (linux-kernel) |
maven → Maven | pkg:maven | parsed | registry | range-validated (maven) |
node, npm → npm | pkg:npm | parsed | registry | range-validated (semver) |
nuget → NuGet | pkg:nuget | parsed | registry | range-validated (nuget) |
composer → Packagist | pkg:composer | parsed | registry | range-validated (composer) |
pub → Pub | pkg:pub | parsed | registry | range-validated (pub) |
pypi, python → PyPI | pkg:pypi | parsed | registry | range-validated (pep440) |
gem → RubyGems | pkg:gem | parsed | registry | range-validated (gem) |
swift → SwiftURL | pkg:swift | parsed | registry | range-validated (swift) |
No advisory source — match_scope: none (22)#
The package identity may still be exact (an official purl type), but no served advisory ecosystem is keyed by these coordinates, so matching is honestly none. Where the version ordering is nonetheless validated (a coordinate gap, not a scheme gap), that readiness is shown — it would take effect only if an advisory source is ever served, via the same coordinated change that enabled the others.
A component here that DECLARES a CPE — an imported SBOM's (Buildroot, Zephyr, OE-core), identity.cpe_map, or a vendored C header the curated table names — can be listed by the opt-in CPE candidate report (scan.cpe_candidates) against a local NVD snapshot. Those are candidates for a human in cpe-candidates.json, never findings, and they do not change match_scope.
A device or module declared under identity.devices — by vendor, product name or model number and firmware version, as industrial CSAF advisories name it — is compared with the CSAF documents the run reads as supplier VEX and written up in device-advisory-context.json. That is context only: never a finding, never a supplier VEX binding and never a match_scope.
| Internal ecosystem | Package identity | Recognition | match_scope | Version-range ordering |
|---|---|---|---|---|
arduino | pkg:generic | parsed | none | equality-only |
bitbucket | pkg:bitbucket | parsed | none | equality-only |
cmake | pkg:generic | parsed | none | equality-only |
cmsis-pack | pkg:generic | parsed | none | equality-only |
cocoapods | pkg:generic | parsed | none | equality-only |
conan | pkg:conan | parsed | none | range-validated (conan) — readiness only, no advisory source |
container | pkg:docker | parsed | none | equality-only |
cpan | pkg:cpan | parsed | none | equality-only |
docker | pkg:docker | parsed | none | equality-only |
esp-idf | pkg:generic | parsed | none | equality-only |
generic | pkg:generic | parsed | none | equality-only |
github | pkg:github | parsed | none | equality-only |
gitlab | pkg:gitlab | parsed | none | equality-only |
helm | pkg:generic | parsed | none | equality-only |
mcuxpresso | pkg:generic | parsed | none | equality-only |
opkg | pkg:generic | parsed | none | equality-only |
platformio | pkg:generic | parsed | none | equality-only |
rpm | pkg:rpm | parsed | none | range-validated (rpm) — readiness only, no advisory source |
silabs-slc | pkg:generic | parsed | none | equality-only |
system | pkg:generic | — | none | equality-only |
vcpkg | pkg:vcpkg | parsed | none | equality-only |
yocto | pkg:yocto | parsed | none | equality-only |