Skip to content

feat: SBOM generation and OmniBOR build provenance (CRA compliance)#10343

Open
MarkAtwood wants to merge 1 commit into
wolfSSL:masterfrom
MarkAtwood:feat/sbom-bomsh
Open

feat: SBOM generation and OmniBOR build provenance (CRA compliance)#10343
MarkAtwood wants to merge 1 commit into
wolfSSL:masterfrom
MarkAtwood:feat/sbom-bomsh

Conversation

@MarkAtwood

Copy link
Copy Markdown
Contributor

Summary

Adds two complementary supply chain transparency targets to the wolfSSL autotools build:

  • make sbom — generates a Software Bill of Materials (SPDX 2.3 + CycloneDX 1.6) for EU Cyber Resilience Act (CRA) compliance
  • make bomsh — generates an OmniBOR artifact dependency graph (cryptographic source-to-binary traceability) using the Bomsh project
  • When both are run, make bomsh enriches the SPDX document with a PERSISTENT-ID gitoid ExternalRef, bridging component identity and build provenance in a single file

make sbom

Produces three files:

File Format
wolfssl-<version>.cdx.json CycloneDX 1.6 JSON
wolfssl-<version>.spdx.json SPDX 2.3 JSON
wolfssl-<version>.spdx SPDX 2.3 tag-value (validated by pyspdxtools)

SBOM contents: name, version, supplier, license (parsed from LICENSING at generation time), copyright, SHA-256 of installed library, CPE, PURL, download location, build configuration defines, and optional third-party dependency versions (liboqs, libz, libxmss, liblms).

Implementation: scripts/gen-sbom (Python 3, stdlib only) stages a make install into a temp directory, hashes the installed library, generates both formats, removes staging. configure.ac detects python3, pyspdxtools, and git via AC_PATH_PROG. make sbom fails with a clear error if either required tool is missing.

make bomsh

Runs a full clean rebuild under bomtrace3 (patched strace — userspace only, no kernel modifications) to produce an OmniBOR artifact graph in omnibor/. If bomsh_sbom.py is available and wolfssl-<version>.spdx.json exists, annotates the SPDX with a PERSISTENT-ID gitoid ExternalRef.

configure.ac detects bomtrace3, bomsh_create_bom.py, and bomsh_sbom.py via AC_PATH_PROG. The raw logfile and conf file are written to the build directory (not /tmp/) to avoid concurrent-build collisions. All generated files removed by make clean.

Install targets

make install-sbom     # installs SBOM files to $(datadir)/doc/wolfssl/
make install-bomsh    # installs omnibor/ and enriched SPDX to $(datadir)/doc/wolfssl/

Documentation

  • doc/SBOM.md — unified reference covering both targets, combined workflow, all output files, implementation notes
  • doc/CRA.md — product-integrator guide: how to incorporate wolfSSL's SBOM artefacts into a downstream product SBOM (SPDX ExternalDocumentRef, CycloneDX component reference), commercial license guidance, OmniBOR gitoid meaning, auditor handoff checklist, links to OpenSSF CRA and SBOM Everywhere SIG guidance
  • INSTALL: sections 21 and 22
  • README.md: brief SBOM/CRA and OmniBOR/Bomsh sections
  • doc/include.am: SBOM.md and CRA.md added to dist_doc_DATA

Test plan

  • ./autogen.sh && ./configure && make && make sbom — verify three SBOM files produced and SPDX validates
  • make install-sbom / make uninstall-sbom — verify files install and remove cleanly
  • make clean — verify all generated files removed
  • With bomtrace3 and bomsh_create_bom.py in PATH: make sbom && make bomsh — verify omnibor/ produced and omnibor.wolfssl-<ver>.spdx.json contains PERSISTENT-ID gitoid ExternalRef
  • Without bomtrace3 in PATH: make bomsh — verify clear error message, non-zero exit
  • Without prior make sbom: make bomsh — verify OmniBOR graph produced, NOTE printed about missing SPDX, no failure

Copilot AI review requested due to automatic review settings April 28, 2026 21:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds build-integrated supply-chain transparency outputs to the Autotools build: SBOM generation (make sbom) and OmniBOR/Bomsh build provenance tracing (make bomsh) to support CRA-style compliance workflows.

Changes:

  • Add scripts/gen-sbom Python generator for CycloneDX 1.6 + SPDX 2.3 JSON SBOM outputs (plus tag-value conversion via pyspdxtools).
  • Wire new sbom, bomsh, and install/uninstall targets into Autotools (configure.ac, Makefile.am), with tool discovery via AC_PATH_PROG.
  • Add end-user documentation (doc/SBOM.md, doc/CRA.md) and reference it from README.md/INSTALL.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
scripts/gen-sbom New Python SBOM generator producing CycloneDX/SPDX JSON with optional dependency metadata.
Makefile.am Adds sbom/bomsh targets, install/uninstall rules, and clean integration.
configure.ac Detects required tools (python3, pyspdxtools, git, bomtrace3, bomsh scripts) and exports needed vars.
doc/include.am Ships new docs in the dist tarball; cleans generated OmniBOR directory.
doc/SBOM.md Primary documentation for SBOM + OmniBOR workflows and outputs.
doc/CRA.md Downstream integrator guidance for CRA-oriented SBOM/provenance usage.
README.md Adds brief pointers to the new SBOM/CRA and OmniBOR features.
INSTALL Adds new sections documenting make sbom / make bomsh usage and prerequisites.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread doc/SBOM.md Outdated
Comment thread Makefile.am Outdated
Comment thread Makefile.am Outdated
Comment thread Makefile.am Outdated
Comment thread Makefile.am Outdated
Comment thread Makefile.am Outdated
Comment thread Makefile.am Outdated
Comment thread scripts/gen-sbom
@Frauschi

Copy link
Copy Markdown
Contributor

Note that we are in the process of removing liblms and libxmss (see #10292), which will simplify the dependency analysis in the python script.

@sameehj sameehj force-pushed the feat/sbom-bomsh branch from 04008be to 2fff508 Compare May 1, 2026 18:05
@MarkAtwood

Copy link
Copy Markdown
Contributor Author

Three CI failures to address:

1. bomsh integration (linux) — upstream repo restructured
The install step checks for .devcontainer/bomtrace3/ in the omnibor/bomsh repo, which no longer exists. Hit our own error string: bomsh repo layout changed; please update CI. Check the current bomsh repo layout and fix the install step.

2. SBOM integration (linux)liboqs-dev not in apt
E: Unable to locate package liboqs-dev — that package isn't in Ubuntu 24.04's default repos. Either build liboqs from source in CI, use a PPA, or make that step conditional.

3. Windows Build Test (x64)tcp bind failed
Build succeeded (0 errors), runtime fails with wolfSSL error: tcp bind failed. Looks like port contention on the Windows runner. Please check if this also fails on master — if so it's pre-existing and not our bug, and we can ignore it.

PRB-master-job failure appears to be a reporting artifact (no test results found), not a real failure.

@Frauschi

Frauschi commented May 5, 2026

Copy link
Copy Markdown
Contributor
  1. Windows Build Test (x64)tcp bind failed

FYI, this will be resolved with #10387

@sameehj sameehj force-pushed the feat/sbom-bomsh branch 2 times, most recently from c6d9f94 to 39aefe7 Compare May 7, 2026 04:26

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #10343

No scan targets match the changed files in this PR. Review skipped.

@sameehj

sameehj commented May 8, 2026

Copy link
Copy Markdown
Contributor

retest this please

@MarkAtwood MarkAtwood left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-merge self-review

Ran a structured pre-merge review across scripts/gen-sbom, scripts/test_gen_sbom.py, .github/workflows/sbom.yml, Makefile.am, and the docs. Five commits result, each listing its closed findings in the trailer:

test(sbom): expand coverage; CI hard-requires pcpp
fix(sbom): correctness fixes in gen-sbom
build(sbom): Makefile.am hygiene
ci(sbom): pin deps, harden token, partial-clone bomsh
docs(sbom): correct NTIA/SPDX claims; fix broken anchor

Real defects fixed (fix(sbom))

  1. parse_options_h URL corruption. re.split(r'/\*|//', raw)[0] truncated PACKAGE_URL "https://..." at the first // inside the URL, emitting PACKAGE_URL = "https: in the SBOM wolfssl:build:* properties. Replaced with a string-literal-aware state machine.
  2. detect_license missed the canonical FSF preamble. or\s+(any\s+)?later failed on or (at your option) any later version (the FSF GPLv2 preamble used in millions of upstream COPYING files); silently mis-detected as GPL-X.0-only. Broadened with a sentence-bounded filler match.
  3. Empty --lib accepted. A misconfigured build pointing --lib at /dev/null or an empty .a silently emitted the well-known empty-file SHA-256 (e3b0c44…b855) as the wolfSSL component checksum; both SPDX and CDX validators accepted it. Hard-fail gate on size 0 with an actionable error; --srcs zero-byte placeholders get a soft warning (cross-compile setups legitimately use them).

Coverage gaps closed (test(sbom))

+42 tests covering detect_license (had zero tests), sha256_file's chunked-read path (the loop body wasn't exercised by the only existing empty-file vector), all four SBOM document generators (generate_cdx / generate_spdx / cdx_dep_component / spdx_dep_package), and the LicenseRef-without-license-text CLI rejection. Independent oracles throughout — SPDX licence list, hashlib one-shot SHA-256, CDX 1.6 / SPDX 2.3 schema field semantics.

TestParseUserSettings.setUp previously called self.skipTest on missing pcpp. The unit job didn't install pcpp, so 9 standalone-path tests silently skipped on every PR run. Now hard-fails with an actionable install hint, and the unit job installs pcpp==1.30.*.

Build hygiene (build(sbom))

Five Makefile.am improvements — none changes user-facing behaviour for any correct invocation; each closes a specific failure mode:

  • bomsh artifact glob quoted for spaces in abs_builddir
  • SOURCE_DATE_EPOCH only exported when git log -1 --format=%ct returned non-empty (silent shallow-clone case)
  • --license-override / --license-text only passed when set (decouples Makefile from gen-sbom's argparse default)
  • install-bomsh switched from a two-tar pipeline (which masked source-side errors due to POSIX sh's pipeline exit-status semantics) to cp -R src/. dst/
  • uninstall-hook depends on uninstall-sbom + uninstall-bomsh instead of duplicating their bodies

CI hardening (ci(sbom))

pcpp==1.30.* pinned, permissions: contents: read at workflow level (defence-in-depth — workflow does no API writes), git clone --filter=blob:none for the bomsh fetch (saves ~10s per run; pinned SHA makes blob filter safe).

Doc corrections (docs(sbom))

  • README.md previously said "Both produce SPDX 2.3 + CycloneDX 1.6 JSON validated against NTIA minimum elements". Neither path runs an NTIA-minimum-elements checker. Only make sbom runs pyspdxtools (SPDX-spec, not NTIA-specific). Corrected.
  • doc/CRA.md named ntia-conformance-checker as enforcing SPDX §10.1 hasExtractedLicensingInfos; it does not (that is pyspdxtools' job). Corrected with explicit text on what ntia-conformance-checker actually validates so a reader cannot be misled into running a malformed LicenseRef SBOM through the wrong tool and getting a false pass.
  • doc/SBOM.md anchor link #3-make-bomsh resolved to the wrong section; fixed to the GFM auto-anchor for §3.1.

Re the Copilot inline review

The Copilot review raised 8 concerns. 7 are addressed: the NOASSERTION CDX wording in SBOM.md §2.4, make bomshmake sbom rebuild ordering, hardcoded library paths replaced with the WOLFSSL_LIB_DSO_BASENAMES glob, scripts/gen-sbom added to EXTRA_DIST, trap-based staging cleanup, and removing the hardcoded licenseListVersion.

The remaining concern — install-bomsh using a non-INSTALL_DATA copy mechanism — is unchanged in intent (this round uses cp -R rather than the previous tar pipeline for clean error propagation but did not adopt find ... | xargs $(INSTALL_DATA)). The OmniBOR tree is a directory of content-addressed binary objects; using $(INSTALL_DATA) per-file is the more automakey approach but adds complexity for a directory whose layout is meant to be preserved verbatim. Open to revisiting if maintainers prefer.

Acknowledgement

@sameehj — the standalone --user-settings / --srcs entry point, SPDX 2.3 LicenseRef compliance, library-discovery glob, and CI workflow shape this PR from "works on my machine" into a production-ready, embedded-customer-friendly tool. The test infrastructure you built was solid. Thanks.

cc @Frauschi for visibility — make clean removes both the doxygen artefacts and BOMSH_OMNIBORDIR via doc/include.am's clean-local:.

@sameehj sameehj force-pushed the feat/sbom-bomsh branch 2 times, most recently from 525918d to cf0bdd9 Compare May 12, 2026 07:50
@sameehj

sameehj commented May 13, 2026

Copy link
Copy Markdown
Contributor

retest this please

@sameehj

sameehj commented May 14, 2026

Copy link
Copy Markdown
Contributor

retest this please

@dgarske dgarske left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skoll Code Review

Scan type: reviewOverall recommendation: COMMENT
Findings: 4 total — 4 posted, 0 skipped
3 finding(s) posted as inline comments (see file-level comments below)

Posted findings

  • [Medium] make sbom does not thread --dep-version; liboqs/zlib version becomes NOASSERTION without pkg-configMakefile.am:409-475 (sbom target)
  • [Low] Redundant/dead branch logic in FIPS product bucket computationscripts/gen-advisory:product_model (FIPS block)
  • [Low] Duplicate pkg-config invocation per dependencyscripts/gen-sbom:cdx_dep_component / spdx_dep_package
  • [Info] Executable-bit inconsistency between gen-sbom (755) and gen-advisory (644)scripts/gen-advisory:1

Review generated by Skoll

Comment thread Makefile.am
Comment thread scripts/gen-sbom
Comment thread scripts/gen-advisory Outdated
@MarkAtwood

Copy link
Copy Markdown
Contributor Author

Good catch on the --dep-version gap. Yes, let's expose a SBOM_DEP_VERSIONS make variable so autotools packagers without pkg-config can still record dep versions.

@sameehj can you pick this up along with the other Skoll findings?

@sameehj

sameehj commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

retest this please

@MarkAtwood MarkAtwood left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Blockers

1. gen-advisory: resolvedknown_affected mapping inversion

_STATE_TO_BUCKET maps resolved to known_affected. This is a semantic inversion — patched products get reported as actively vulnerable in the CSAF output. Downstream scanners will tell operators to patch what's already fixed. Should be 'resolved': 'fixed'. Same gap for resolved_with_pedigree which is absent from the mapping entirely and falls through to the known_affected default.

2. gen-advisory: unmapped states default to known_affected

bucket = _STATE_TO_BUCKET.get(state, 'known_affected')

false_positive and any other unmapped CycloneDX analysis state silently becomes "actively vulnerable." Either map them correctly (e.g. false_positiveknown_not_affected) or raise an error on unknown states rather than defaulting to the worst-case bucket.

3. Makefile.am: uninstall-advisory missing from uninstall-hook

uninstall-hook: uninstall-sbom uninstall-bomsh

uninstall-advisory is absent. make install-advisory && make uninstall leaves advisory files behind.

4. Makefile.am: install-advisory glob loop breaks on empty match

@for f in $(ADVISORY_OUT_DIR)/*.json; do \
    $(INSTALL_DATA) "$$f" $(DESTDIR)$(advisorydir)/; \
done

On POSIX sh (without nullglob), when the glob matches nothing the loop body executes with the literal glob string, calling $(INSTALL_DATA) on a nonexistent file. Add [ -f "$$f" ] || continue as the first statement in the loop body.


High

5. CVSS scoring errors in CVE records

Both CVE records use privilegesRequired: LOW. Neither vulnerability requires system account access — obtaining a TLS cert (5501) or sending network traffic (5778) are PR:N scenarios. CVE-2026-5778 also uses userInteraction: PASSIVE for a sniffer crash triggered by network traffic with no human involvement — should be UI:N. These errors understate the severity scores.

6. gen-sbom TOCTOU in gitoid_blob_sha256

os.path.getsize(path) is called before open(path, 'rb'). If the file changes between the two calls, the gitoid header encodes the wrong size. Fix: use os.fstat(f.fileno()).st_size after opening the file descriptor (same approach git itself uses).

7. bomsh_verify.py path traversal via unsanitized gitoid

The gitoid string extracted from the SPDX document is used directly in os.path.join(omnibor_objects_dir, gid[:2], gid[2:]) without validating that it is a 40-character hex string. A crafted SPDX file with gitoid:blob:sha1:../../../etc/shadow passes the prefix check and enables path traversal. Impact is read-only (os.path.isfile), but still an info-disclosure risk when SPDX comes from untrusted build artifacts. Fix: re.fullmatch(r'[0-9a-f]{40}', gid) before path construction.

8. EXTRA_DIST hardcodes CVE filenames

EXTRA_DIST += advisories/records/CVE-2026-5501.json \
              advisories/records/CVE-2026-5778.json

Every new CVE record requires a manual Makefile.am edit or it's silently missing from make dist tarballs. The failure is silent — make dist succeeds, downstream make advisory fails. Use a dist-hook glob instead.


Medium

9. CI actions pinned to tags, not SHAs

All uses: lines reference floating tags (actions/checkout@v4, etc.). For a supply-chain provenance workflow this is the most visible inconsistency — the SBOM workflow's own build inputs are mutable. The bomsh clone correctly uses a full commit SHA; actions and the liboqs/strace clones should follow the same pattern.

10. CSAF category: 'self' with a generic landing page URL

'references': [{'summary': '...', 'url': WOLFSSL_ADVISORIES_URL, 'category': 'self'}]

CSAF 2.0 mandatory test 6.1.20 requires the self reference to point to the canonical location of this specific document, not a generic advisories page. This will fail conformance validation when the document is published.

11. VEX overlay schema doesn't require state

The overlayEntry object has no required array, so the core VEX determination field (state) is optional. An empty overlay entry {} validates silently against the schema. Add "required": ["state"] to the overlayEntry definition.

@sameehj

sameehj commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

retest this please

@sameehj

sameehj commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Code Review

Blockers

1. gen-advisory: resolvedknown_affected mapping inversion

_STATE_TO_BUCKET maps resolved to known_affected. This is a semantic inversion — patched products get reported as actively vulnerable in the CSAF output. Downstream scanners will tell operators to patch what's already fixed. Should be 'resolved': 'fixed'. Same gap for resolved_with_pedigree which is absent from the mapping entirely and falls through to the known_affected default.

Won't change, by design. The bucket applies to the CVE's vulnerable version ranges, which stay known_affected permanently; the patched release is emitted separately into fixed in the per-product loop. Mapping resolved → fixed would mislabel the old vulnerable ranges as patched. Added resolved_with_pedigree to the explicit map (the real gap). Documented in-code.

2. gen-advisory: unmapped states default to known_affected

bucket = _STATE_TO_BUCKET.get(state, 'known_affected')

false_positive and any other unmapped CycloneDX analysis state silently becomes "actively vulnerable." Either map them correctly (e.g. false_positiveknown_not_affected) or raise an error on unknown states rather than defaulting to the worst-case bucket.

Fixed

3. Makefile.am: uninstall-advisory missing from uninstall-hook

uninstall-hook: uninstall-sbom uninstall-bomsh

uninstall-advisory is absent. make install-advisory && make uninstall leaves advisory files behind.

Fixed

4. Makefile.am: install-advisory glob loop breaks on empty match

@for f in $(ADVISORY_OUT_DIR)/*.json; do \
    $(INSTALL_DATA) "$$f" $(DESTDIR)$(advisorydir)/; \
done

On POSIX sh (without nullglob), when the glob matches nothing the loop body executes with the literal glob string, calling $(INSTALL_DATA) on a nonexistent file. Add [ -f "$$f" ] || continue as the first statement in the loop body.

Fixed

High

5. CVSS scoring errors in CVE records

Both CVE records use privilegesRequired: LOW. Neither vulnerability requires system account access — obtaining a TLS cert (5501) or sending network traffic (5778) are PR:N scenarios. CVE-2026-5778 also uses userInteraction: PASSIVE for a sniffer crash triggered by network traffic with no human involvement — should be UI:N. These errors understate the severity scores.

Fixed

6. gen-sbom TOCTOU in gitoid_blob_sha256

os.path.getsize(path) is called before open(path, 'rb'). If the file changes between the two calls, the gitoid header encodes the wrong size. Fix: use os.fstat(f.fileno()).st_size after opening the file descriptor (same approach git itself uses).

Fixed

7. bomsh_verify.py path traversal via unsanitized gitoid

The gitoid string extracted from the SPDX document is used directly in os.path.join(omnibor_objects_dir, gid[:2], gid[2:]) without validating that it is a 40-character hex string. A crafted SPDX file with gitoid:blob:sha1:../../../etc/shadow passes the prefix check and enables path traversal. Impact is read-only (os.path.isfile), but still an info-disclosure risk when SPDX comes from untrusted build artifacts. Fix: re.fullmatch(r'[0-9a-f]{40}', gid) before path construction.

Fixed

8. EXTRA_DIST hardcodes CVE filenames

EXTRA_DIST += advisories/records/CVE-2026-5501.json \
              advisories/records/CVE-2026-5778.json

Every new CVE record requires a manual Makefile.am edit or it's silently missing from make dist tarballs. The failure is silent — make dist succeeds, downstream make advisory fails. Use a dist-hook glob instead.

Fixed

Medium

9. CI actions pinned to tags, not SHAs

All uses: lines reference floating tags (actions/checkout@v4, etc.). For a supply-chain provenance workflow this is the most visible inconsistency — the SBOM workflow's own build inputs are mutable. The bomsh clone correctly uses a full commit SHA; actions and the liboqs/strace clones should follow the same pattern.

Fixed

10. CSAF category: 'self' with a generic landing page URL

'references': [{'summary': '...', 'url': WOLFSSL_ADVISORIES_URL, 'category': 'self'}]

CSAF 2.0 mandatory test 6.1.20 requires the self reference to point to the canonical location of this specific document, not a generic advisories page. This will fail conformance validation when the document is published.

Fixed

11. VEX overlay schema doesn't require state

The overlayEntry object has no required array, so the core VEX determination field (state) is optional. An empty overlay entry {} validates silently against the schema. Add "required": ["state"] to the overlayEntry definition.
Fixed

@sameehj

sameehj commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

retest this please

@MarkAtwood

Copy link
Copy Markdown
Contributor Author

Holding merge until after the current release — wolfSSL/wolfssl is in code freeze. Will pick this up once master reopens.

@dgarske dgarske left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skoll Code Review

Scan type: reviewOverall recommendation: COMMENT
Findings: 2 total — 2 posted, 0 skipped
2 finding(s) posted as inline comments (see file-level comments below)

Posted findings

  • [Medium] bomsh recipe shell block lacks set -e; a failed nested make sbom is maskedMakefile.am:698-720
  • [Low] make advisory / install-advisory targets undocumented in INSTALL and READMEMakefile.am:598-644

Review generated by Skoll

Comment thread Makefile.am Outdated
Comment thread Makefile.am
@sameehj

sameehj commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

retest this please

@dgarske dgarske self-requested a review June 29, 2026 16:59
@MarkAtwood MarkAtwood requested a review from cconlon June 29, 2026 19:21
@MarkAtwood

MarkAtwood commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

@cconlon — one focused ask: please review this PR (#10343) only. It's the keystone of the SBOM / EU CRA work and the one piece with real logic to look at — the gen-sbom script plus the make sbom / make bomsh plumbing. All prior review findings are resolved; dgarske's recent Skoll pass left one open item (a set -e in the bomsh recipe) which I'll fold in.

The rest of the rollout does not need your eyes — flagging only so you know it's out there, not asking you to review it:

Happy to walk through #10343 whenever.

Add tooling to produce Software Bills of Materials and build provenance
for wolfSSL, supporting EU Cyber Resilience Act (CRA) obligations.

SBOM generation:
- New `make sbom` target producing SPDX 2.3 output with NTIA minimum
  elements, urn:uuid document namespaces, and SPDX LicenseRef compliance.
- Reproducible library discovery across autotools and CMake builds, with
  liboqs recorded as a linked artefact.
- Standalone `scripts/gen-sbom` for embedded / RTOS / custom-builder
  flows that do not use the main build system, plus --srcs-file,
  --no-artifact-hash, and hash-source options.

Build provenance (OmniBOR / bomsh):
- End-to-end bomsh tracing of the built binaries with ArtifactID
  insertion, snapshotting the traced library before libtool relink and
  hashing the bomsh-traced binary.
- `scripts/bomsh_verify.py` to validate provenance against the traced
  gitoid.

Security advisories:
- `scripts/gen-advisory` generating CSAF 2.0 and CycloneDX VEX, with a
  `make` target, VEX overlay schema/example, and CWE name data.

Docs, tests, and CI:
- doc/SBOM.md and doc/CRA.md, plus README/INSTALL updates.
- Unit and regression tests for gen-sbom and gen-advisory.
- New sbom.yml and advisory.yml workflows: SPDX validation via
  pyspdxtools, CSAF validation, bomsh provenance verification, SBOM
  artifact archiving, macOS coverage, and actions pinned to SHAs.

Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
@sameehj sameehj force-pushed the feat/sbom-bomsh branch from 47dba82 to b053002 Compare July 1, 2026 07:25
@dgarske dgarske requested a review from douzzer July 1, 2026 17:15
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.

7 participants