UNPKG

@cyclonedx/cyclonedx-esbuild

Version:

Creates CycloneDX Software Bill of Materials (SBoM) from esbuild projects

208 lines (159 loc) 9.79 kB
# CycloneDX SBOM generator for _esbuild_ [![shield_npm-version]][link_npm] [![shield_gh-workflow-test]][link_gh-workflow-test] [![shield_coverage]][link_codacy] [![shield_ossf-best-practices]][link_ossf-best-practices] [![shield_license]][license_file] [![shield_website]][link_website] [![shield_slack]][link_slack] [![shield_groups]][link_discussion] [![shield_twitter-follow]][link_twitter] ---- Create _[CycloneDX]_ Software Bill of Materials (SBOM) from _[esbuild]_ projects. This package provides both an **[esbuild plugin](#esbuild-plugin)** and a **[CLI tool](#cli-tool)** to generate CycloneDX SBOMs from your builds. This tooling uses the linkages generated by _esbuild_ to create <!-- a dependency graph -- not yet -- see https://github.com/CycloneDX/cyclonedx-esbuild/issues/11 --> an inventory which only contain the dependencies that are actually used (after [tree-shaking](https://esbuild.github.io/api/#tree-shaking)). ## Features * 🔌 **esbuild plugin** for automatic SBOM generation during builds * 🖥️ **CLI tool** for generating SBOMs from esbuild metafiles * 🎯 Supports multiple **CycloneDX spec versions** (1.2, 1.3, 1.4, 1.5, 1.6, 1.7) * 🔍 Extracts components and dependencies from bundled projects * 📝 **License evidence gathering** (experimental) ***Validates** generated SBOMs against CycloneDX schema * 🔄 **Reproducible output** option for consistent SBOM generation * 📊 Works with **TypeScript**, **Angular**, and other modern frameworks ## Requirements * _Node.js_ `>= 20.18` * _esbuild_ (required when using the plugin; not required for CLI-only usage) ## Installing Use your preferred package manager and install as a dev-dependency: ```shell npm install --save-dev @cyclonedx/cyclonedx-esbuild pnpm add --save-dev @cyclonedx/cyclonedx-esbuild yarn add --dev @cyclonedx/cyclonedx-esbuild ``` ## Usage ### Esbuild Plugin The _esbuild_ plugin automatically generates an SBOM during your build process. #### Esbuild Plugin Options & Configuration <!-- the following table is based on `src/plugin.ts`::`CycloneDxEsbuildPluginOptions` --> | Name | Type | Default | Description | |:-----|:----:|:-------:|:------------| | **`specVersion`** | `{string}`<br/> one of: `"1.2"`, `"1.3"`, `"1.4"`, `"1.5"`, `"1.6"`, `"1.7"` | `"1.6"` | Which version of [CycloneDX-spec] to use.<br/> Supported values depend on the installed dependency [CycloneDX-javascript-library]. | | **outputFile** | `{string}` | `"bom.json"` | Path to the output file. | | **gatherLicenseTexts** | `boolean` | `false` | Search for license files in components and include them as license evidence.<br/> This feature is experimental. | | **outputReproducible** | `{boolean}` | `false` | Whether to go the extra mile and make the output reproducible.<br/> This requires more resources, and might result in loss of time- and random-based-values. | | **mcType** | `{string}` | `"application"` | Set the MainComponent's type.<br/> See [list of valid values](https://cyclonedx.org/docs/1.7/json/#metadata_component_type). | | **validate** | `{boolean \| undefined}` | `undefined` | Validate resulting BOM before outputting.<br/> Validation is skipped, if requirements not met. | #### Esbuild Plugin Example ```javascript const esbuild = require('esbuild'); const { cyclonedxEsbuildPlugin } = require('@cyclonedx/cyclonedx-esbuild'); /** @type {import('@cyclonedx/cyclonedx-esbuild').CycloneDxEsbuildPluginOptions} */ const cyclonedxEsbuildPluginOptions = { specVersion: '1.7', outputFile: 'bom.json' } esbuild.build({ // ... plugins: [ cyclonedxEsbuildPlugin(cyclonedxEsbuildPluginOptions), ] }); ``` See extended [examples]. ### CLI Tool The Command Line Interface for generating SBOMs from [esbuild metafiles](https://esbuild.github.io/api/#metafile). #### CLI Call Calling the CLI depends on the used install method. Here are examples for the various package managers and setups: ```shell npm exec -- cyclonedx-esbuild --help pnpm exec cyclonedx-esbuild --help yarn exec cyclonedx-esbuild --help ``` #### CLI Help Page ```text Usage: cyclonedx-esbuild [options] <metafile> Create CycloneDX Software Bill of Materials (SBOM) from esbuild metafile. Arguments: metafile Path to esbuild metafile Options: --ewd, --esbuild-working-dir Working dir used in the esbuild process. --gather-license-texts Search for license files in components and include them as license evidence. This feature is experimental. (default: false) --sv, --spec-version <version> Which version of CycloneDX spec to use. (choices: "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", default: "1.6") --output-reproducible Whether to go the extra mile and make the output reproducible. This requires more resources, and might result in loss of time- and random-based-values. (env: BOM_REPRODUCIBLE) -o, --output-file <file> Path to the output file. Set to "-" to write to STDOUT. (default: write to STDOUT) --validate Validate resulting BOM before outputting. Validation is skipped, if requirements not met. See the README. --no-validate Disable validation of resulting BOM. --mc-type <type> Type of the main component. (choices: "application", "firmware", "library", default: "application") -v, --verbose Increase the verbosity of messages. Use multiple times to increase the verbosity even more. -V, --version output the version number -h, --help display help for command ``` ### Use with Angular For _Angular_ projects using _esbuild_ (Angular 17+), you can generate SBOMs from the build stats. ```jsonc // package.json { "scripts": { "build:app": "ng build --stats-json", "build:sbom": "cyclonedx-esbuild --gather-license-texts --output-reproducible -o dist/bom.json dist/stats.json", "build": "npm run build:app && npm run build:sbom" } } ``` See an example here: [integration with Angular20](https://github.com/CycloneDX/cyclonedx-esbuild/tree/1.0-dev/tests/_testbeds/angular20-yarn). ## Internals This tooling utilizes the [CycloneDX library][CycloneDX-javascript-library] to generate the actual data structures. Besides the class `CycloneDxEsbuildPlugin` and the interface `CycloneDxEsbuildPluginOptions`, this _esbuild_ plugin and this tool does **not** expose any additional _public_ API or classes - all code is intended to be internal and might change without any notice during version upgrades. However, the CLI is stable - you may call it programmatically like: ```javascript const { execFileSync } = require('child_process') const { constants: { MAX_LENGTH: BUFFER_MAX_LENGTH } } = require('buffer') const sbom = JSON.parse(execFileSync(process.execPath, [ '../path/to/this/package/bin/cyclonedx-exbuild-cli.js', '--spec-version', '1.7', '--output-file', '-' // additional CLI args ], { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'buffer', maxBuffer: BUFFER_MAX_LENGTH })) ``` ## Development & Contributing Feel free to open issues, bug reports or pull requests. See the [CONTRIBUTING][contributing_file] file for details. ## License Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE][license_file] file for the full license. [license_file]: https://github.com/CycloneDX/cyclonedx-esbuild/blob/1.0-dev/LICENSE [contributing_file]: https://github.com/CycloneDX/cyclonedx-esbuild/blob/1.0-dev/CONTRIBUTING.md [examples]: https://github.com/CycloneDX/cyclonedx-esbuild/tree/1.0-dev/examples [CycloneDX]: https://cyclonedx.org/ [esbuild]: https://esbuild.github.io [CycloneDX-javascript-library]: https://github.com/CycloneDX/cyclonedx-javascript-library/ [shield_gh-workflow-test]: https://img.shields.io/github/actions/workflow/status/CycloneDX/cyclonedx-esbuild/nodejs.yml?branch=1.0-dev&logo=GitHub&logoColor=white "tests" [shield_npm-version]: https://img.shields.io/npm/v/%40cyclonedx%2fcyclonedx-esbuild/latest?label=npm&logo=npm&logoColor=white "npm" [shield_ossf-best-practices]: https://img.shields.io/cii/percentage/11463?label=OpenSSF%20best%20practices "OpenSSF best practices" [shield_coverage]: https://img.shields.io/codacy/coverage/4900a38bdc544b2283695447e9513ab5?logo=Codacy&logoColor=white "test coverage" [shield_license]: https://img.shields.io/github/license/CycloneDX/cyclonedx-esbuild?logo=open%20source%20initiative&logoColor=white "license" [shield_website]: https://img.shields.io/badge/https://-cyclonedx.org-blue.svg "homepage" [shield_slack]: https://img.shields.io/badge/slack-join-blue?logo=Slack&logoColor=white "slack join" [shield_groups]: https://img.shields.io/badge/discussion-groups.io-blue.svg "groups discussion" [shield_twitter-follow]: https://img.shields.io/badge/Twitter-follow-blue?logo=Twitter&logoColor=white "twitter follow" [link_website]: https://cyclonedx.org/ [link_gh-workflow-test]: https://github.com/CycloneDX/cyclonedx-esbuild/actions/workflows/nodejs.yml?query=branch%3A1.0-dev [link_codacy]: https://app.codacy.com/gh/CycloneDX/cyclonedx-esbuild/dashboard [link_ossf-best-practices]: https://www.bestpractices.dev/projects/11463 [link_npm]: https://www.npmjs.com/package/@cyclonedx/cyclonedx-esbuild [link_slack]: https://cyclonedx.org/slack/invite [link_discussion]: https://groups.io/g/CycloneDX [link_twitter]: https://twitter.com/CycloneDX_Spec