feat: add make sbom target#536
Conversation
Adds sbom, install-sbom, and uninstall-sbom targets. Runs gen-sbom to produce CDX and SPDX outputs. Requires WOLFSSL_DIR pointing to a wolfssl tree with the feat/sbom-embedded branch (includes gen-sbom).
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds build-system support for generating and installing SBOM artifacts (CycloneDX + SPDX) via new make targets, integrating wolfSSL’s gen-sbom script and SPDX validation tooling.
Changes:
- Split libtool version-info into separately substituted components for reuse in make rules.
- Add
sbom,install-sbom, anduninstall-sbomtargets to generate/validate and install SBOM outputs. - Detect
python3andpyspdxtoolsat configure-time for use by the SBOM targets.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| configure.ac | Exposes library version components and discovers SBOM tool dependencies (python3, pyspdxtools) for make targets. |
| Makefile.am | Implements SBOM generation/validation and install/uninstall targets; wires output files into CLEANFILES. |
| $(PYTHON3) $(WOLFSSL_DIR)/scripts/gen-sbom \ | ||
| --name wolftpm \ | ||
| --version $(PACKAGE_VERSION) \ | ||
| --supplier "wolfSSL Inc." \ | ||
| --license-file $(srcdir)/LICENSE \ | ||
| --options-h $(abs_builddir)/wolftpm/options.h \ | ||
| --lib $(abs_builddir)/_sbom_staging$(libdir)/libwolftpm.so.@WOLFTPM_LIBRARY_VERSION_FIRST@.@WOLFTPM_LIBRARY_VERSION_SECOND@.@WOLFTPM_LIBRARY_VERSION_THIRD@ \ | ||
| $(if $(SBOM_LICENSE_OVERRIDE),--license-override $(SBOM_LICENSE_OVERRIDE)) \ | ||
| $(if $(SBOM_LICENSE_TEXT),--license-text $(SBOM_LICENSE_TEXT)) \ | ||
| --cdx-out $(abs_builddir)/$(SBOM_CDX) \ | ||
| --spdx-out $(abs_builddir)/$(SBOM_SPDX) |
| fi | ||
| rm -rf $(abs_builddir)/_sbom_staging | ||
| $(MAKE) install DESTDIR=$(abs_builddir)/_sbom_staging | ||
| $(PYTHON3) $(WOLFSSL_DIR)/scripts/gen-sbom \ |
| --license-file $(srcdir)/LICENSE \ | ||
| --options-h $(abs_builddir)/wolftpm/options.h \ | ||
| --lib $(abs_builddir)/_sbom_staging$(libdir)/libwolftpm.so.@WOLFTPM_LIBRARY_VERSION_FIRST@.@WOLFTPM_LIBRARY_VERSION_SECOND@.@WOLFTPM_LIBRARY_VERSION_THIRD@ \ | ||
| $(if $(SBOM_LICENSE_OVERRIDE),--license-override $(SBOM_LICENSE_OVERRIDE)) \ | ||
| $(if $(SBOM_LICENSE_TEXT),--license-text $(SBOM_LICENSE_TEXT)) \ | ||
| --cdx-out $(abs_builddir)/$(SBOM_CDX) \ | ||
| --spdx-out $(abs_builddir)/$(SBOM_SPDX) |
| --supplier "wolfSSL Inc." \ | ||
| --license-file $(srcdir)/LICENSE \ | ||
| --options-h $(abs_builddir)/wolftpm/options.h \ | ||
| --lib $(abs_builddir)/_sbom_staging$(libdir)/libwolftpm.so.@WOLFTPM_LIBRARY_VERSION_FIRST@.@WOLFTPM_LIBRARY_VERSION_SECOND@.@WOLFTPM_LIBRARY_VERSION_THIRD@ \ |
aidangarske
left a comment
There was a problem hiding this comment.
Skoll Multi-Scan Review
Modes: review + review-security + bugsOverall recommendation: REQUEST_CHANGES
Findings: 7 total — 7 posted, 0 skipped
7 finding(s) posted as inline comments (see file-level comments below)
Posted findings
- [High] [review+review-security+bugs] Autotools sbom target reconstructs the libtool library filename incorrectly; breaks on next version-info bump and on macOS/static builds —
Makefile.am:181 - [High] [review+review-security+bugs] CMake sbom target hard-codes Unix shared-library layout; fails on Windows, static, and multi-config builds —
CMakeLists.txt:860-884 - [Medium] [bugs] CMake sbom target uses cmake -E rm, unavailable on the declared minimum CMake 3.16 —
CMakeLists.txt:874,891 - [Medium] [review] New SBOM targets have no automated coverage —
Makefile.am:144-188 - [Low] [review] install-sbom mixes absolute and relative artifact paths; only works when run from the build dir —
Makefile.am:184-194 - [Low] [review+review-security] CMake return() used at directory scope to skip the SBOM block; fragile if code is appended —
CMakeLists.txt:844-853 - [Low] [review-security] CMake version.h regex uses [ \t] which does not match a tab in CMake's regex dialect —
CMakeLists.txt:803-806
Review generated by Skoll
| --supplier "wolfSSL Inc." \ | ||
| --license-file $(srcdir)/LICENSE \ | ||
| --options-h $(abs_builddir)/wolftpm/options.h \ | ||
| --lib $(abs_builddir)/_sbom_staging$(libdir)/libwolftpm.so.@WOLFTPM_LIBRARY_VERSION_FIRST@.@WOLFTPM_LIBRARY_VERSION_SECOND@.@WOLFTPM_LIBRARY_VERSION_THIRD@ \ |
There was a problem hiding this comment.
🔴 [High] Autotools sbom target reconstructs the libtool library filename incorrectly; breaks on next version-info bump and on… · Logic
The sbom target points gen-sbom --lib at libwolftpm.so.@WOLFTPM_LIBRARY_VERSION_FIRST@.@WOLFTPM_LIBRARY_VERSION_SECOND@.@WOLFTPM_LIBRARY_VERSION_THIRD@, i.e. libwolftpm.so.\<current>.\<revision>.\<age>, reconstructed from libtool's current:revision:age version-info fields (currently 17:0:0). libtool actually installs the real ELF file as libNAME.so.(current-age).age.revision: the first component should be current-age (not current) and the trailing two are age.revision, swapped relative to this recipe's revision.age. configure.ac's own comments confirm the installed soname is current-age, making the mapping internally inconsistent. It works today only because all three components collapse to 17.0.0 for 17:0:0; the next release with a nonzero revision/age (e.g. 17:1:0) makes libtool install libwolftpm.so.17.0.1 while the recipe looks for libwolftpm.so.17.1.0, so --lib points at a nonexistent file and make sbom fails. The hardcoded .so.X.Y.Z and $(libdir) are also non-portable: macOS installs libwolftpm.\<n>.dylib, static-only builds produce libwolftpm.a, and MinGW installs the DLL runtime under $(bindir) — none of which this path can locate. Severity views across modes: review=High/BLOCK, bugs=Medium, review-security=Low; strictest kept.
Fix: Do not reconstruct the versioned name from version-info components. After the staged install, discover the actual installed artifact under the staged $(libdir)/$(bindir) (glob libwolftpm.so.*, libwolftpm*.dylib, *wolftpm*.dll, or dereference the unversioned libwolftpm.so dev symlink) and fail clearly if none is found. If the versioned name must be kept, compute the first component as current-age and order the trailing components as age.revision.
| set(SBOM_SPDX_TV "${CMAKE_BINARY_DIR}/wolftpm-${SBOM_VERSION}.spdx") | ||
| set(SBOM_STAGING "${CMAKE_BINARY_DIR}/_sbom_staging") | ||
|
|
||
| # Staged install path. install(TARGETS wolftpm) above hardcodes |
There was a problem hiding this comment.
🔴 [High] CMake sbom target hard-codes Unix shared-library layout; fails on Windows, static, and multi-config builds · Logic
The CMake sbom target computes SBOM_LIB = ${SBOM_STAGING}/lib/libwolftpm${CMAKE_SHARED_LIBRARY_SUFFIX} and passes it to gen-sbom after cmake --install, hard-coding both the lib/ staging subdir and a Unix shared-object name rather than the real target artifact. This diverges from the actual install layout in several supported configurations: (1) With -DBUILD_SHARED_LIBS=OFF (option defaults ON at line 73) the installed artifact is libwolftpm.a under ARCHIVE DESTINATION lib, so --lib points at a .so/.dylib that was never produced. (2) On Windows shared builds, install(TARGETS) uses RUNTIME DESTINATION bin, DLLs go under bin/ and typically drop the lib prefix (wolftpm.dll), so the path never matches. (3) For multi-config generators (Visual Studio, Xcode) the cmake --install omits --config $\<CONFIG>, so building the sbom target can install/hash the wrong or unbuilt configuration. In each case gen-sbom fails with a bare file-not-found. Severity views: review=High/BLOCK, bugs=Medium, review-security=Low; strictest kept.
Fix: Derive the artifact from CMake target metadata via generator expressions ($\<TARGET_FILE_NAME:wolftpm> plus the platform-specific staged destination — bin/ on Windows, lib/ elsewhere), add --config $\<CONFIG> to the install for multi-config generators, and either support static builds explicitly or reject BUILD_SHARED_LIBS=OFF for the sbom target with a clear FATAL_ERROR.
| VERBATIM | ||
| # Stage a clean install so gen-sbom inspects the same artifact layout | ||
| # the user would actually ship. | ||
| COMMAND ${CMAKE_COMMAND} -E rm -rf ${SBOM_STAGING} |
There was a problem hiding this comment.
🟠 [Medium] CMake sbom target uses cmake -E rm, unavailable on the declared minimum CMake 3.16 · API Contract Violations
The sbom custom target runs ${CMAKE_COMMAND} -E rm -rf ${SBOM_STAGING} twice (lines 874 and 891). The cmake -E rm subcommand was introduced in CMake 3.17, but this file declares cmake_minimum_required(VERSION 3.16) (line 22). On a host with exactly CMake 3.16 — a version the project claims to support — cmake --build build --target sbom fails with cmake -E rm: unknown command before any SBOM is produced. The main build is unaffected; only the new opt-in target breaks.
Fix: Use the 3.16-compatible ${CMAKE_COMMAND} -E remove_directory ${SBOM_STAGING} (handles a missing directory gracefully and matches rm -rf intent), or raise the minimum CMake version for this target path.
|
|
||
| .PHONY: sbom install-sbom uninstall-sbom | ||
|
|
||
| sbom: |
There was a problem hiding this comment.
🟠 [Medium] New SBOM targets have no automated coverage · test
The PR adds non-trivial autotools and CMake SBOM generation paths, but includes no automated smoke coverage for either target; the PR body lists only manual test steps. A lightweight test would have caught the artifact-path and platform assumptions in the new target logic (see the autotools libtool-filename and CMake shared-library-layout findings).
Fix: Add CI or a build-system smoke test that provides a minimal fake WOLFSSL_DIR/scripts/gen-sbom, runs make sbom and cmake --build --target sbom, and asserts the expected output files are produced or that prerequisite errors are clear.
| --lib $(abs_builddir)/_sbom_staging$(libdir)/libwolftpm.so.@WOLFTPM_LIBRARY_VERSION_FIRST@.@WOLFTPM_LIBRARY_VERSION_SECOND@.@WOLFTPM_LIBRARY_VERSION_THIRD@ \ | ||
| $(if $(SBOM_LICENSE_OVERRIDE),--license-override $(SBOM_LICENSE_OVERRIDE)) \ | ||
| $(if $(SBOM_LICENSE_TEXT),--license-text $(SBOM_LICENSE_TEXT)) \ | ||
| --cdx-out $(abs_builddir)/$(SBOM_CDX) \ |
There was a problem hiding this comment.
🔵 [Low] install-sbom mixes absolute and relative artifact paths; only works when run from the build dir · convention
The sbom recipe writes outputs to $(abs_builddir)/$(SBOM_CDX) (absolute) at line 184, while install-sbom installs the bare $(SBOM_CDX), $(SBOM_SPDX), and $(SBOM_SPDX_TV) relative to the current directory at line 192. These only line up when make install-sbom runs from the build directory; VPATH/out-of-tree distcheck-style builds or invoking from a subdir would look in the wrong place.
Fix: Use $(abs_builddir)/$(SBOM_*) consistently in install-sbom (and CLEANFILES) to match where the sbom target actually writes the artifacts.
| "'pyspdxtools' not found in PATH (install: pip install spdx-tools)") | ||
| endif() | ||
|
|
||
| if(NOT _sbom_error STREQUAL "") |
There was a problem hiding this comment.
🔵 [Low] CMake return() used at directory scope to skip the SBOM block; fragile if code is appended · Logic
When an SBOM prerequisite (python3/pyspdxtools/WOLFSSL_DIR) is missing, the code defines a failing fallback sbom target and then calls return(). This block is guarded by if(BUILD_WOLFTPM_LIB) at top-level directory scope (not inside a function), so return() ends processing of the remainder of CMakeLists.txt, not just the SBOM if block. It is harmless today only because the SBOM section is the last block in the file (ends at the endif() on line 896); any install(), target, or export logic added after it would be silently skipped in the common no-SBOM build. Severity views: review=Low/NIT, review-security=Info; strictest kept.
Fix: Avoid return() at directory scope for control flow. Select the fallback vs. real target with if()/else() (or a nested-if scoped to the SBOM section), or move the SBOM logic into a function/included module so the early exit cannot skip future directives.
| # this file drifts out of sync with the header. | ||
| file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/wolftpm/version.h" | ||
| _sbom_version_line | ||
| REGEX "^#define[ \t]+LIBWOLFTPM_VERSION_STRING[ \t]+\"") |
There was a problem hiding this comment.
🔵 [Low] CMake version.h regex uses [ \t] which does not match a tab in CMake's regex dialect · Logic
The SBOM version is parsed with REGEX "^#define[ \t]+LIBWOLFTPM_VERSION_STRING[ \t]+\"". CMake's regex engine does not interpret \t as a tab escape; inside the bracket expression [ \t] is the literal set {space, backslash, 't'}. It matches today only because the distributed wolftpm/version.h uses space separators. If version.h were ever regenerated with tab separators, file(STRINGS ... REGEX) would return no match, _sbom_version_line would be empty, and the target would abort via the FATAL_ERROR at 807-811. Currently benign — defense-in-depth only.
Fix: Since version.h is generated with single spaces, match [ ]+ explicitly, or embed a literal tab in the character class if tab tolerance is actually desired.
Summary
Adds
make sbom,make install-sbom, andmake uninstall-sbomtargets to the autotools build..sofor hashingcc -dM -Efor the options snapshotgen-sbom(from wolfsslscripts/gen-sbom) to produce CycloneDX and SPDX outputspyspdxtoolsUsage
Outputs:
wolftpm-<version>.cdx.json,wolftpm-<version>.spdx.json,wolftpm-<version>.spdxRequirements
WOLFSSL_DIRmust point to a wolfssl source tree containingscripts/gen-sbom(available on thefeat/sbom-embeddedbranch of wolfssl)python3andpip install spdx-toolson the build hostTest plan
./configure --with-wolfssl=... && make && make sbom WOLFSSL_DIR=...pyspdxtools --infile wolftpm-*.spdx.jsonpasses validationCMake
sbomtargetThe cmake build now has an equivalent
sbomcustom target, so SBOM generation works the same way whether you build with autotools or cmake.cmake -B build -DWOLFSSL_DIR=/path/to/wolfssl/source . cmake --build build cmake --build build --target sbomOutputs land in the build directory:
wolftpm-<version>.cdx.json,wolftpm-<version>.spdx.json,wolftpm-<version>.spdx.Notes:
wolftpm/version.h(LIBWOLFTPM_VERSION_STRING), not from the cmakeproject()call, so the cmake and autotools SBOMs stay bit-identical in the version field even if the two drift.wolftpm/options.h(the real compile-time option set) rather than a rawcc -dMdump, which would only capture compiler builtins. This keeps the cmake SBOM consistent with what autotools produces via--options-h.WOLFSSL_DIRandpython3/pyspdxtoolsare validated at configure time. A missing prerequisite does not break a normalcmake --build; thesbomtarget simply fails with a clear message when invoked. A wrong-DWOLFSSL_DIR=(explicit opt-in with a bad path) hard-errors at configure time.-DCMAKE_INSTALL_LIBDIR=libif needed; the staged library is read fromlib/.