Repository navigation
tools,build: add CycloneDX SBOM generation - #66761
BethGriggs wants to merge 2 commits into
Conversation
Add tools/generate_sbom.py, a stdlib-only Python 3 script that writes a
CycloneDX 1.5 SBOM describing the bundled dependencies of the Node.js
binary.
The script reads config.gypi to determine which dependencies are active
in the current build, then extracts version strings from whichever file
each dependency uses to record its version: C headers, CMakeLists.txt,
package.json, Cargo.toml and others. A dependency whose version cannot
be read is reported as "unknown" with a warning rather than failing the
run. Dependencies satisfied by a system library or disabled via a
configure flag are emitted with scope "excluded", so the document
reflects the build that was configured.
Output defaults to out/Release/node-v{version}-sbom.json.
New Makefile targets:
make sbom - generate the SBOM (requires ./configure first)
make test-sbom - validate the generated SBOM
doc/contributing/maintaining/maintaining-dependencies.md now asks for a
DEP_CATALOG entry when adding a dependency, so new deps do not silently
go missing from the SBOM.
Unit tests in test/tools/test_generate_sbom.py cover catalog structural
correctness, the version extractors, scope resolution and deps/
coverage. They run under the existing `make tooltest` target.
Refs: nodejs/security-wg#1115
Assisted-by: IBM Bob
Signed-off-by: Beth Griggs <bethanyngriggs@gmail.com>
|
Review requested:
|
|
Last time I gave it a try I was having an hard time because cyclondx crashed trying to analyze the vendored deps. Glad to see this issue has been fixed |
richardlau
left a comment
There was a problem hiding this comment.
I think this is good start. It doesn't look like much to maintain (a large part appears to be the catalog).
Maybe in the future we can deduplicate version discovery between the deps_updaters, scanning in https://github.com/nodejs/nodejs-dependency-vuln-assessments and this tool, but certainly doesn't have to happen in the first pass.
| 'version_fn': lambda root: version_from_readme_node( | ||
| root / 'deps/inspector_protocol/README.node', 'Revision'), | ||
| }, | ||
| # --- Always-bundled ICU, JavaScript and Rust dependencies --- |
There was a problem hiding this comment.
Most of these are not always bundled.
e.g.
- icu could be omitted with
configure --with-intl=none - npm could be omitted with
configure --without-npm - amaro could be omitted with
configure --without-amaro - Rust dependencies could be omitted if
configure --v8-disable-temporal-support, or no Rust compiler present
Corepack is no longer bundled by default (but can be included with configure --with-corepack).
There was a problem hiding this comment.
Oops, the comment was just incorrect π€¦π»ββοΈ . I've tried to take into account the various optionals in 7221ccd. They will now not be included in the SBOM when omitted.
I do still need to check all options are covered and how we keep them up-to-date - I'll explore if I can add test cases to help with that.
Previously, `generate_sbom.py` emitted components for dependencies that were not linked into the binary, marking them with the `excluded` scope. Drop those components so the SBOM only lists what ships in the build. Add `excluded_when` conditions to catalog entries whose inclusion depends on configure flags: * perfetto: only included with `--with-perfetto` * inspector_protocol: omitted when the inspector is disabled * icu: omitted with `--with-intl=none` * npm: omitted with `--without-npm` * corepack: only included with `--with-corepack` * node_crates: omitted when Temporal support is disabled or when `--shared-temporal_capi` is used Mark icu, corepack and node_crates as `optional` since they are not always bundled. Skip components that resolve to `excluded` in `generate_sbom()` and drop the now-redundant `excluded` filtering when building the root component's `dependsOn` list and when warning about unreadable versions. Signed-off-by: Beth Griggs <bethanyngriggs@gmail.com> Assisted-by: IBM Bob
|
@marco-ippolito, ah, this is taking a different approach and doesn't use any SBOM tooling. The idea is that we inspect the |
This is a proof-of-concept for build-time SBOM generation in Node.js core (nodejs/security-wg#1115).
The PR adds
tools/generate-sbom.py, a stdlib-only Python 3 script that produces a CycloneDX 1.5 JSON Software Bill of Materials covering all bundled runtime dependencies of the Node.js binary.The script reads
config.gypi(produced by./configure) to determine which dependencies are active in the current build, then extracts version strings from committed C headers,CMakeLists.txtfiles,package.jsonfiles,and other metadata sources across all
deps/subdirectories. Dependencies disabled via configure flags or satisfied by system libraries are listed withscope: excludedso the document accurately reflects the actual build.Pre-emptive questions
package.jsonfiles. New JS files inlib/flow throughconfig.gypiautomatically. The only manual step is oneDEP_CATALOGentry when a new C/C++ dep is added - a CI test enforces this so a missing entry fails rather than producing a silent gap.deps/npm/lib/utils/sbom-cyclonedx.js. SPDX support could be added later behind a--formatflag../configurejust needs to have run. Python is already the language of the entire build toolchain (configure.py,gyp_node.py,install.py).make build/make release?SBOM snippets