Skip to content

feat: add CRA SBOM generation (make sbom)#10342

Closed
MarkAtwood wants to merge 1 commit intowolfSSL:masterfrom
MarkAtwood:feat/sbom
Closed

feat: add CRA SBOM generation (make sbom)#10342
MarkAtwood wants to merge 1 commit intowolfSSL:masterfrom
MarkAtwood:feat/sbom

Conversation

@MarkAtwood
Copy link
Copy Markdown

Summary

  • Adds make sbom producing CycloneDX 1.6 JSON, SPDX 2.3 JSON, and SPDX 2.3 tag-value SBOMs for EU Cyber Resilience Act (CRA) compliance
  • SBOM generation handled by scripts/gen-sbom (Python 3, stdlib only); validates via pyspdxtools
  • SBOMs include SHA-256 of the installed library, CPE, PURL, license (detected from LICENSING), copyright, build config from options.h, and optional external deps (liboqs, libxmss, liblms, libz) as separate components
  • Version detection for deps without pkg-config (libxmss, liblms) uses git describe --tags --always on the source tree root
  • Adds install-sbom / uninstall-sbom targets installing to $(datadir)/doc/wolfssl/
  • Adds doc/SBOM.md, INSTALL section, and README.md one-liner

configure.ac changes

  • AC_SUBST for ENABLED_LIBOQS/LIBXMSS/LIBLMS/LIBZ so dep flags set at ./configure time are visible in the generated Makefile
  • AC_SUBST([LIBLMS_ROOT]) + LIBLMS_ROOT="" default (mirrors existing XMSS_ROOT handling) so gen-sbom can locate the source tree for git describe
  • AC_PATH_PROG([GIT]) to find git robustly at configure time rather than relying on PATH at make sbom time

Test plan

  • ./configure && make && make sbom on a default build — produces all three output files, pyspdxtools validates without error
  • make sbom without python3 in PATH — fails with clear error message
  • make sbom without pyspdxtools in PATH — fails with clear error message
  • ./configure --with-libz && make && make sbom — zlib appears as a component in both SBOMs with version from pkg-config
  • make install-sbom — installs three files under $(datadir)/doc/wolfssl/
  • make uninstall-sbom — removes installed files
  • make clean — removes generated SBOM files

Adds `make sbom` producing CycloneDX 1.6 and SPDX 2.3 SBOMs
for EU Cyber Resilience Act compliance.

Generation is handled by scripts/gen-sbom (Python 3, stdlib only).
The script stages a `make install`, hashes the installed
libwolfssl.so, generates both formats, then removes the staging
directory. pyspdxtools validates the SPDX JSON and converts it
to tag-value (.spdx).

Output files (all versioned):
  wolfssl-<ver>.cdx.json   CycloneDX 1.6 JSON
  wolfssl-<ver>.spdx.json  SPDX 2.3 JSON
  wolfssl-<ver>.spdx       SPDX 2.3 tag-value

SBOMs include: SHA-256 of the library, CPE, PURL, license
detected from the LICENSING file, copyright, and build
configuration (options.h defines as CDX properties). Optional
external dependencies (liboqs, libxmss, liblms, libz) appear as
separate components when enabled.

Version detection for deps without pkg-config (libxmss, liblms)
uses `git describe --tags --always` on the source tree root.

configure.ac changes:
- AC_SUBST ENABLED_LIBOQS/LIBXMSS/LIBLMS/LIBZ so the dep flags
  set during ./configure are visible in the generated Makefile
- AC_SUBST LIBLMS_ROOT (XMSS_ROOT was already exported by
  wolfssl) so gen-sbom can locate the source tree for git describe
- AC_PATH_PROG([GIT]) to find git robustly at configure time
  rather than relying on PATH at make sbom time
- Initialize LIBLMS_ROOT="" before the liblms detection block,
  mirroring how XMSS_ROOT is defaulted in the disabled branch

Also adds: doc/SBOM.md, INSTALL section 21, README one-liner,
install-sbom / uninstall-sbom targets.
Copilot AI review requested due to automatic review settings April 28, 2026 20:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds build-time SBOM generation and installation targets to support EU Cyber Resilience Act (CRA) compliance, producing CycloneDX 1.6 and SPDX 2.3 outputs.

Changes:

  • Add a Python-based SBOM generator (scripts/gen-sbom) to emit CycloneDX JSON and SPDX JSON.
  • Integrate SBOM generation/validation into Autotools (make sbom, install-sbom, uninstall-sbom) and wire required tool detection via configure.ac.
  • Add SBOM documentation and a README/INSTALL entry describing usage and outputs.

Reviewed changes

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

Show a summary per file
File Description
scripts/gen-sbom New Python generator that builds CycloneDX + SPDX JSON SBOMs and captures build/dependency metadata.
Makefile.am Adds sbom targets, staging install for hashing, and pyspdxtools conversion to tag-value.
configure.ac Exposes dependency enablement/root vars and detects python3, pyspdxtools, and git for SBOM generation.
doc/SBOM.md Documents SBOM generation, outputs, manual validation, and dependency version detection behavior.
INSTALL Adds a section describing SBOM prerequisites, usage, and install/uninstall targets.
README.md Adds a short section pointing users to make sbom and SBOM docs.

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

Comment thread configure.ac

AM_CFLAGS="$AM_CFLAGS -DHAVE_LIBLMS"
ENABLED_LIBLMS="yes"
LIBLMS_ROOT=$tryliblmsdir
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

LIBLMS_ROOT is assigned without quoting, so paths containing whitespace will be split by the shell during configure and the value exported into the Makefile will be incorrect. Quote the assignment (and any similar path-valued assignments) so --with-liblms="/path with spaces" works reliably.

Suggested change
LIBLMS_ROOT=$tryliblmsdir
LIBLMS_ROOT="$tryliblmsdir"

Copilot uses AI. Check for mistakes.
Comment thread Makefile.am
Comment on lines +376 to +378
rm -rf $(abs_builddir)/_sbom_staging
$(MAKE) install DESTDIR=$(abs_builddir)/_sbom_staging
$(PYTHON3) $(srcdir)/scripts/gen-sbom \
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The staging directory is only removed on the success path. If make install, gen-sbom, or pyspdxtools fails, _sbom_staging can be left behind, which is messy and can affect subsequent runs (especially in CI). Consider making cleanup unconditional (e.g., using a shell trap or a single shell block that guarantees rm -rf ... executes on exit/failure).

Copilot uses AI. Check for mistakes.
Comment thread Makefile.am
Comment on lines +393 to +395
rm -rf $(abs_builddir)/_sbom_staging
$(PYSPDXTOOLS) --infile $(abs_builddir)/$(SBOM_SPDX) \
--outfile $(abs_builddir)/$(SBOM_SPDX_TV)
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The staging directory is only removed on the success path. If make install, gen-sbom, or pyspdxtools fails, _sbom_staging can be left behind, which is messy and can affect subsequent runs (especially in CI). Consider making cleanup unconditional (e.g., using a shell trap or a single shell block that guarantees rm -rf ... executes on exit/failure).

Copilot uses AI. Check for mistakes.
Comment thread scripts/gen-sbom
prints a warning if the file cannot be parsed.
"""
try:
text = open(license_file).read()
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

These reads don’t use context managers and don’t specify an encoding. Using with open(..., encoding="utf-8", errors="replace") avoids file descriptor leaks and makes behavior deterministic across platforms/locales (especially for LICENSING text parsing).

Copilot uses AI. Check for mistakes.
Comment thread scripts/gen-sbom
"""Parse wolfssl/options.h and return sorted deduplicated list of
(name, value) pairs for every #define found."""
try:
text = open(path).read()
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

These reads don’t use context managers and don’t specify an encoding. Using with open(..., encoding="utf-8", errors="replace") avoids file descriptor leaks and makes behavior deterministic across platforms/locales (especially for LICENSING text parsing).

Copilot uses AI. Check for mistakes.
Comment thread scripts/gen-sbom
for chunk in iter(lambda: f.read(65536), b''):
h.update(chunk)
except OSError as e:
sys.exit(f"ERROR: cannot read library for hashing: {e}")
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This error omits the library path being hashed, which makes diagnosing miscomputed/incorrect --lib paths harder. Include path in the message (e.g., “cannot read library for hashing at : ...”) so failures are actionable.

Suggested change
sys.exit(f"ERROR: cannot read library for hashing: {e}")
sys.exit(f"ERROR: cannot read library for hashing at {path}: {e}")

Copilot uses AI. Check for mistakes.
Comment thread doc/SBOM.md
Comment on lines +97 to +98
source tree is unavailable or `git` is not found, version is recorded as
`NOASSERTION`.
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This statement doesn’t match the implementation for CycloneDX: when a dependency version is unknown, CycloneDX output omits version and purl (while SPDX uses NOASSERTION for versionInfo). Update this section to reflect the format-specific behavior to avoid confusing users comparing outputs.

Suggested change
source tree is unavailable or `git` is not found, version is recorded as
`NOASSERTION`.
source tree is unavailable or `git` is not found, SPDX records `NOASSERTION`
for `versionInfo`, while CycloneDX omits `version` and `purl`.

Copilot uses AI. Check for mistakes.
@MarkAtwood
Copy link
Copy Markdown
Author

Superseded by a combined SBOM + OmniBOR build provenance branch (feat/sbom-bomsh). Will re-submit as a single PR covering both features together.

@MarkAtwood MarkAtwood closed this Apr 28, 2026
@github-actions
Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

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.

3 participants