Skip to content

feat(sbom): report the source language of cataloged packages - #328

Draft
reyreavman wants to merge 4 commits into
feat/sbom/targeted-dir-scanfrom
feat/sbom/gost-source-langs
Draft

reyreavman wants to merge 4 commits into
feat/sbom/targeted-dir-scanfrom
feat/sbom/gost-source-langs

Conversation

@reyreavman

Copy link
Copy Markdown
Collaborator

Summary

SBOMs of stapel images now carry the GOST:source_langs property the FSTEC tabular component listing is generated from: every component cataloged through a packages directive is stamped with the source language of that directive's ecosystem, and werf sbom merge rolls the languages up to the image and product level. Nothing to configure; the property appears on rebuild.

What

Per-package property

  • A component cataloged by a packages directive carries GOST:source_langs: go-modGo, python-pip/python-poetry/python-uvPython, rust-cargoRust, javascript-npm/javascript-yarn/javascript-pnpmJavaScript, lua-rockLua.
  • The value is a single property with the languages joined by ", " — never repeated properties, because the ISPRAS exporters read only the first property with a given name and split its value on commas.
  • Components installed by os-pm carry no property: pm's report has no language field yet, and guessing a language for prebuilt binaries in a regulator-bound listing is not acceptable.
  • Dockerfile images do not change: werf generates no SBOM for them.

Merge-level aggregation

  • After werf sbom merge, the product component carries the sorted, deduplicated union of the languages of all images.
  • In the container output format, each image's container component additionally carries the union of the languages of the components below it; the oss format has no container components and gets only the product-level property.
  • Languages already present on a component (e.g. from a user-imported BOM) are unioned with the aggregated ones, not suppressed.

Cache

  • Cached SBOM artifacts are regenerated once: the artifact format version is bumped 4 → 5, and the directive's language is part of the scan checksum.

Why

The "programming language(s)" column of the tabular component listing (ППК) is produced by the ISPRAS exporters from GOST:source_langs; without the property the column stays empty for every package, image and product row. The language comes from the werf.yaml packages directive, not from syft package metadata: stapel images are scanned one directive at a time, so the attribution is exact and does not depend on what syft happens to emit. Deriving the language from purl types (the efs-sbom approach) was rejected as the primary source — it is a heuristic, while the directive type is ground truth the user already declared.

Every component cataloged through a packages directive now carries the
GOST:source_langs property required by the FSTEC component listing: a single
property with the languages of the ecosystem that installed the package, which
is the form the ISPRAS tooling reads (it takes the first property with that name
and splits its value on commas).

The language comes from the packages directive itself, registered per ecosystem
and carried down to the per-directive scan, so it does not depend on scanner
metadata. Packages installed by os-pm are prebuilt binaries of an arbitrary
language and stay without the property. The SBOM artifact format version is
bumped so that cached SBOMs are regenerated.

Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
A merged SBOM now carries GOST:source_langs on the product component and, in
the container format, on the container component of every image, holding the
sorted union of the languages of the components below it. Without it the image
and product rows of the tabular component listing, which is generated from
these properties, stayed empty while the package rows were filled in.

Languages already present on a component (e.g. from a user-imported BOM) are
unioned with the aggregated ones instead of suppressing them.

Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Assert GOST:source_langs on a component cataloged by the python-pip and
javascript-npm directives, so the language registry stays wired from the
packages directive down to the generated SBOM.

Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Describe how GOST:source_langs is derived from the packages directive, why
os-pm packages carry no language, and how the languages are collected on merge.

Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
@reyreavman

Copy link
Copy Markdown
Collaborator Author

Verification

  • Scoped e2e (task test:e2e paths="./test/e2e/sbom" labelFilter="gost" parallel=1) against a local registry on macOS arm64: the new "source language" specs (pip + npm directives) pass; the two os-pm image-level GOST overrides specs fail identically on a clean tree (linux/amd64 builder base image on an arm64 host), not caused by this branch.
  • Mutation: suppressing aggregated languages on a container component that already had some → pkg/sbom/ispras unit test failed during development.
  • Mutation not run for the stamping loop in scanCatalogerDir: the unit test asserting per-component languages in pkg/build/sbom_step_test.go was written after the implementation; deleting the stamping loop is the mutation to try.

Review focus

  • pkg/sbom/ispras/gost.go: union semantics for pre-existing GOST:source_langs on a container component — the other GOST properties use "keep existing" instead; the divergence is deliberate (languages are a set, attack surface is an override).
  • Value format decision (single comma-joined property) rests on the ISPRAS exporters' get_prop returning only the first property with a name; checked against 3p-ispras-sbom-checker:master and efs-sbom 1.0.5.

Follow-up

  • Stamp GOST:source_langs on os-pm components once pm ships srcLanguages in /var/lib/pm/index.json (pm branch feat/src-languages-in-info): read the field in ParsePmInstalledJSON and set it in ConvertToCycloneDX; aggregation picks it up with no further changes.
  • BLOCKER: PR feat(sbom): generate file-based package SBOMs without docker.sock #307 (feat/sbom/targeted-dir-scan) is the base branch of this stacked PR and has to merge first; retarget this PR to main afterwards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant