github.com/CycloneDX/sbom-utility@v0.16.0/README.md (about)

     1  [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
     2  [![License](https://img.shields.io/badge/CycloneDX-v1.2,1.3,1.4,1.5,1.6-darkcyan.svg)](https://opensource.org/licenses/Apache-2.0)
     3  [![License](https://img.shields.io/badge/SPDX-v2.1,2.2,2.3-purple.svg)](https://opensource.org/licenses/Apache-2.0)
     4  
     5  # sbom-utility
     6  
     7  The **`sbom-utility`** was designed to be an API platform to validate, analyze and edit **Bills-of-Materials (BOMs)**. Initially, it was created to **validate** either CycloneDX *or* SPDX-formatted BOMs against official, versioned JSON schemas as published by their respective standards communities.
     8  
     9  - *Organizations may also design and supply **"custom JSON schema"** variants to the validate command which are perhaps designed to assure additional data-compliance requirements are met.*
    10  
    11  The utility also offers commands that support analysis and editing of BOM document data including **trim**, **patch** (IETF RFC 6902) and **diff** *(experimental)*.
    12  
    13  In addition, the utility features "report" commands that can easily *extract*, *filter*, *list* and *summarize* **component**, **service**, **license**, **resource**, **vulnerability** and other BOM information using the utility's powerful, SQL-like query command. The **query** command allows **select**-ion of specific data **from** anywhere in the BOM document **where** data values match specified (regex) patterns.
    14  
    15  - *Report output can be produced in several formats (e.g., `txt`, `csv`, `md` (markdown) and `json`) to accommodate further processing.*
    16  
    17  > **Note**: *This utility supports all CycloneDX BOM variants, such as Software (**SBOM**), Hardware (**HBOM**), Manufacturing (**MBOM**), Machine Learning and AI (**MLBOM**), Cryptographic (**CBOM**), etc.*
    18  
    19  ---
    20  
    21  ### Command Overview
    22  
    23  The following commands, which operate against input BOMs and their data, are offered by the utility:
    24  
    25  | Command <font size="-1">*[`subcommand`]*</font> | Description |
    26  | :-- | :-- |
    27  | **[validate](#validate)**  | Enables validation of SBOMs against their declared format (e.g., SPDX, CycloneDX) and version (e.g., "2.3", "1.6", etc.) using their JSON schemas.|
    28  | **[patch](#patch)** | Applies a JSON patch file, as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/), to an input JSON BOM file. |
    29  | **[trim](#trim)** | Removes specified JSON information from the input JSON BOM document and produce output BOMs with reduced or targeted sets of information.</br></br>*A "SQL-like" set of parameters allows for fine-grained specification of which fields should be trimmed from which document paths.* |
    30  | **[diff](#diff)** | **Experimental**[<sup>1</sup>](#experimental-commands):  Displays the delta between two similar BOM versions in JSON (diff) patch format as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/). *Please read "recommendations"  before running.* |
    31  | **[query](#query)** | Retrieves JSON data from BOMs using SQL-style query statements (i.e., `--select <data fields> --from <BOM object> --where <field=regex>`). The JSON data can be used to create custom listings or reports. |
    32  | **[component](#component)** **[`list`](#component-list-command)** | Produces filterable listings of hardware or software components declared in the BOM. |
    33  | **[license](#license)** **[`list`](#license-list-subcommand)** | Produces filterable listings of license data declared in the BOM along with the associated component or service. Includes *"usage policy"* determinations as declared in the `license.json` configuration file. |
    34  | **[license](#license)** **[`policy`](#license-policy-subcommand)** | Produces filterable listings of software and data license information and associated license usage policies as defined a `license.json` configuration file. |
    35  | **[resource `list`](#resource)** | Produces filterable listings of resources (i.e., components and services) declared in the BOM. |
    36  | **[schema `list`](#schema)** | Produces filterable listings of schema formats, versions and variants supported by the `validation` command.</br></br> **Note**: Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file (see the `schema` command's [adding schemas](#adding-schemas) section). |
    37  | **[vulnerability `list`](#vulnerability)** | produces filterable listings of vulnerabilities declared in the BOM (i.e., CycloneDX Vulnerability Exploitability eXchange (**VEX**)) data or independently stored CycloneDX Vulnerability Disclosure Report (**VDR**) data stored in the BOM format. |
    38  
    39  > **Experimental commands**:
    40  *Testing, feedback and helpful suggestions and code commits are appreciated on experimental commands.*
    41  
    42  ---
    43  
    44  ### Project Index
    45  
    46  - [Installation](#installation)
    47  - [Running](#running)
    48  - [Commands](#commands)
    49  - [Contributing](#contributing)
    50  - [Design considerations](#design-considerations)
    51  - [Development](#development)
    52  - [Testing](#testing)
    53  - [Releasing](#releasing)
    54  - [BOM References](#bom-references)
    55    - [CycloneDX](#cyclonedx), [SPDX](#spdx)
    56  
    57  ---
    58  
    59  ### Installation
    60  
    61  Download and decompress the correct archive file (i.e., `.tar` for Unix/Linux systems and `.zip` for Windows) for your target system's architecture and operating system from the releases page within this repository.
    62  
    63  - [https://github.com/CycloneDX/sbom-utility/releases](https://github.com/CycloneDX/sbom-utility/releases)
    64  
    65  The source archive will contain the following files under the root directory:
    66  
    67  - `sbom-utility` - binary executable. This is all most need for non-customized configurations.
    68  - `LICENSE` - the software license for the utility (i.e. Apache 2)
    69  - `sbom-utility-<version>.sbom.json` - a simple Software Bill-of-Materials (SBOM) for the utility
    70  
    71  as well as sample configuration files:
    72  
    73  - `config.json` *(optional)* - copy of the default schema configuration file for optional customization (to be passed on the command line)
    74  - `license.json` *(optional)* - copy of the default license policy configuration file for optional customization (to be passed on the command line)
    75  - `custom.json` *(experimental, unused)* - custom validation configuration file
    76  
    77  ---
    78  
    79  ## Running
    80  
    81  For convenience, the default `config.json` and optional `license.json` configuration files have been embedded in the executable and used.  *You can provide your own versions of these files on the command line using the `--config-schema` or `--config-license` flags respectively.*
    82  
    83  - **Note**: *When providing configuration files using command line flags, the executable attempts to load them from the same path where the executable is run from. If you choose to keep them in a different directory, you will have to supply their location relative to the executable along with the filename.*
    84  
    85  ##### MacOS - Granting executable permission
    86  
    87  On MacOS, the utility is not a registered Apple application and may warn you that it cannot open it the first time. If so, you will need to explicitly permit the executable to be "opened" on your system acknowledging it trusted.  This process is initiated from the Finder application by using `ctrl-click` on the executable file and agreeing using the "Open" button.
    88  
    89  - See how to ["Open a Mac app from an unidentified developer"](https://support.apple.com/guide/mac-help/open-a-mac-app-from-an-unidentified-developer-mh40616/mac)
    90  
    91  ---
    92  
    93  ## Commands
    94  
    95  This section provides detailed descriptions of all commands, supported flags and output formats along with usage examples.
    96  
    97  All commands generate consistent [exit codes](#exit-codes) as well as share some [persistent flags](#persistent-flags) which are described here:
    98  
    99  - [Exit codes](#exit-codes): Including: *`0`: no error, `1`: application error, `2`: validation error, etc.*
   100  - [Persistent flags](#persistent-flags) Including: *`--input`, `--output`, `--format`, `--quiet`, `--where`, etc.*
   101  
   102  Convenient links to each command:
   103  
   104  - [validate](#validate): Validates BOM data against declared or required JSON schema.
   105  - [trim](#trim): Removes uninteresting or necessary fields and data from a BOM.
   106  - [patch](#patch): Patches BOMs using IETF RFC 6902 records.
   107  - [diff](#diff): *(Experimental)*: Displays the differences between two similar BOMs. *Please read recommendations before executing.*
   108  - [query](#query): Extracts JSON objects and fields from a BOM using SQL-like queries.
   109  - [component list](#component): Lists all component information found in a BOM.
   110  - [license](#license)
   111    - [list](#license-list-subcommand): Lists all license information found in a BOM.
   112    - [policy](#license-policy-subcommand): Lists configurable license usage policies found in the `license.json` file.
   113  - [resource list](#resource): Lists all resource information by type (e.g., components, services).
   114  - [schema list](#schema): Lists supported JSON schemas by BOM format, version and variant.
   115  - [vulnerability list](#vulnerability): Lists vulnerability (i.e., `VEX`) information included in a BOM or standalone `VDR` BOM.
   116  - [completion](#completion): Generates command-line completion scripts for the this utility.
   117  - [help](#help): Displays help and usage information for the utility or currently specified command.
   118  
   119  ---
   120  
   121  ### Exit codes
   122  
   123  All commands return a numeric exit code (i.e., a POSIX exit code) for use in automated processing where `0` indicates success and a non-zero value indicates failure of some kind designated by the number.
   124  
   125  The SBOM Utility always returns one of these 3 codes to accommodate logic in BASH (shell) scripting:
   126  
   127  - `0`= no error (valid)
   128  - `1`= application error
   129  - `2`= validation error
   130  
   131  ##### Example: exit code
   132  
   133  This example uses the `schema` list command to verify its exit code:
   134  
   135  ```bash
   136  ./sbom-utility schema list
   137  ```
   138  
   139  verify the exit code:
   140  
   141  ```bash
   142  echo $?
   143  ```
   144  
   145  which returns `0` (zero) or "no error":
   146  
   147  ```bash
   148  0
   149  ```
   150  
   151  ---
   152  
   153  ### Persistent flags
   154  
   155  This section describes some of the important command line flags that apply to most of the utility's commands.
   156  
   157  - [format flag](#format-flag): with `--format`
   158  - [indent flag](#indent-flag): with `--indent`
   159  - [input flag](#input-flag): with `--input` or `-i`
   160  - [output flag](#output-flag): with `--output` or `-o`
   161  - [quiet flag](#quiet-flag): with `--quiet` or `-q`
   162  - [where flag](#where-flag-output-filtering): with `--where`
   163  
   164  #### Format flag
   165  
   166  All `list` subcommands support the `--format` flag with the following values:
   167  
   168  - `txt`: text (tabbed tables)
   169  - `csv`: Comma Separated Value (CSV), e.g., for spreadsheets
   170  - `md`: Markdown (GitHub-compliant tables)
   171  
   172  Some commands, which can output lists of JSON objects, also support JSON format using the `json` value.
   173  
   174  ##### Example: `--format` flag
   175  
   176  This example uses the `--format` flag on the `schema` command to output in markdown:
   177  
   178  ```bash
   179  ./sbom-utility schema --format md -q
   180  ```
   181  
   182  ```md
   183  |name|format|version|variant|file (local)|url (remote)|
   184  |:--|:--|:--|:--|:--|:--|
   185  |CycloneDX v1.5|CycloneDX|1.5|(latest)|schema/cyclonedx/1.5/bom-1.5.schema.json|https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.5.schema.json|
   186  |CycloneDX v1.4|CycloneDX|1.4|(latest)|schema/cyclonedx/1.4/bom-1.4.schema.json|https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.4.schema.json|
   187  |CycloneDX/specification/master/schema/bom-1.3-strict.schema.json|
   188  |CycloneDX v1.3|CycloneDX|1.3|(latest)|schema/cyclonedx/1.3/bom-1.3.schema.json|https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3.schema.json|
   189  |CycloneDX/specification/master/schema/bom-1.2-strict.schema.json|
   190  |CycloneDX v1.2|CycloneDX|1.2|(latest)|schema/cyclonedx/1.2/bom-1.2.schema.json|https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2.schema.json|
   191  |SPDX v2.3.1 (development)|SPDX|SPDX-2.3|development|schema/spdx/2.3.1/spdx-schema.json|https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3.1/schemas/spdx-schema.json|
   192  |SPDX v2.3|SPDX|SPDX-2.3|(latest)|schema/spdx/2.3/spdx-schema.json|https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json|
   193  |SPDX v2.2.2|SPDX|SPDX-2.2|(latest)|schema/spdx/2.2.2/spdx-schema.json|https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.2/schemas/spdx-schema.json|
   194  |SPDX v2.2.1|SPDX|SPDX-2.2|2.2.1|schema/spdx/2.2.1/spdx-schema.json|https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json|
   195  ```
   196  
   197  #### Indent flag
   198  
   199  This flag supplies an integer to any command that encodes JSON output to determine how many spaces to indent nested JSON elements.  If not specified, the default indent is `4` (spaces).
   200  
   201  ##### Example: indent flag on the query command
   202  
   203  ```bash
   204  ./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --indent 2 -q
   205  ```
   206  
   207  output with `indent 2`:
   208  
   209  ```json
   210  {
   211    "name": "juice-shop",
   212    "version": "11.1.2"
   213  }
   214  ```
   215  
   216  ```bash
   217  ./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --indent 6 -q
   218  ```
   219  
   220  output with `indent 6`:
   221  
   222  ```json
   223  {
   224        "name": "juice-shop",
   225        "version": "11.1.2"
   226  }
   227  ```
   228  
   229  #### Input flag
   230  
   231  All `list` subcommands and the `validate` command support the `--input-file <filename>` flag (or its short-form `-i <filename>`) to declare file contents (i.e., BOM data) the commands will read and operate on.
   232  
   233  #### Standard input (stdin)
   234  
   235  All commands that support the input flag can also accept data from standard input or `stdin` by using the `-` (dash) character as the value instead of a filename.
   236  
   237  ##### Example of stdin using pipe
   238  
   239  ```bash
   240   cat examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json | ./sbom-utility resource list -i -
   241  ```
   242  
   243  ##### Example of stdin using redirect
   244  
   245  ```bash
   246  ./sbom-utility validate -i - < examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json
   247  ```
   248  
   249  #### Output flag
   250  
   251  All `list` subcommands and the `validate` command support the `--output-file <filename>` flag (or its short-form `-o <filename>`) to send formatted output to a file.
   252  
   253  ##### Example: `--output-file` flag
   254  
   255  This example uses the `schema` command to output to a file named `output.txt` with format set to `csv`:
   256  
   257  ```bash
   258  ./sbom-utility schema --format csv -o output.csv
   259  ```
   260  
   261  Verify the contents of `output.csv` contain CSV formatted output:
   262  
   263  ```bash
   264  cat output.csv
   265  ```
   266  
   267  ```csv
   268  Name,Format,Version,Variant,File (local),URL (remote)
   269  CycloneDX v1.5 (development),CycloneDX,1.5,development,schema/cyclonedx/1.5/bom-1.5-dev.schema.json,https://raw.githubusercontent.com/CycloneDX/specification/v1.5-dev/schema/bom-1.5.schema.json
   270  CycloneDX v1.4,CycloneDX,1.4,(latest),schema/cyclonedx/1.4/bom-1.4.schema.json,https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.4.schema.json
   271  CycloneDX v1.3,CycloneDX,1.3,(latest),schema/cyclonedx/1.3/bom-1.3.schema.json,https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3.schema.json
   272  CycloneDX v1.2,CycloneDX,1.2,(latest),schema/cyclonedx/1.2/bom-1.2.schema.json,https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2.schema.json
   273  SPDX v2.3.1 (development),SPDX,SPDX-2.3,development,schema/spdx/2.3.1/spdx-schema.json,https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3.1/schemas/spdx-schema.json
   274  SPDX v2.3,SPDX,SPDX-2.3,(latest),schema/spdx/2.3/spdx-schema.json,https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json
   275  SPDX v2.2.2,SPDX,SPDX-2.2,(latest),schema/spdx/2.2.2/spdx-schema.json,https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.2/schemas/spdx-schema.json
   276  SPDX v2.2.1,SPDX,SPDX-2.2,2.2.1,schema/spdx/2.2.1/spdx-schema.json,https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json
   277  ```
   278  
   279  - **Note**: You can verify that `output.csv` loads within a spreadsheet app like MS Excel.
   280  
   281  #### Quiet flag
   282  
   283  All commands support the `--quiet` flag. By default, the utility outputs informational (INFO), warning (WARNING) and error (ERROR) text along with the  actual command results to `stdout`.  If you wish to only see the command results (JSON) or report (tables) you can run any command in "quiet mode" by simply supplying the `--quiet` or its short-form `-q` flag.
   284  
   285  ##### Example: `--quiet` flag
   286  
   287  This example shows the `--quiet` flag being used on the `schema` command to turn off or "quiet" any informational output so that only the result table is displayed.
   288  
   289  ```bash
   290  ./sbom-utility schema list --quiet
   291  ```
   292  
   293  ```bash
   294  name                          format     version   variant      file (local)                                     url (remote)
   295  ----                          ------     -------   -------      ------------                                     ------------
   296  CycloneDX v1.5                CycloneDX  1.5       (latest)     schema/cyclonedx/1.5/bom-1.5.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.5.schema.json
   297  CycloneDX v1.4                CycloneDX  1.4       (latest)     schema/cyclonedx/1.4/bom-1.4.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.4.schema.json
   298  CycloneDX v1.3                CycloneDX  1.3       (latest)     schema/cyclonedx/1.3/bom-1.3.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3.schema.json
   299  CycloneDX v1.2                CycloneDX  1.2       (latest)     schema/cyclonedx/1.2/bom-1.2.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2.schema.json
   300  SPDX v2.3.1 (development)     SPDX       SPDX-2.3  development  schema/spdx/2.3.1/spdx-schema.json               https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3.1/schemas/spdx-schema.json
   301  ...
   302  ```
   303  
   304  #### Where flag (output filtering)
   305  
   306  All `list` subcommands support the `--where`  flag. It can be used to filter output results based upon matches to regular expressions (regex) by using the output list's column titles as keys.
   307  
   308  Multiple key-value (i.e., column-title=regex) pairs can be provided on the same `--where` filter flag using commas.
   309  
   310  **Syntax**: `[--where key=regex[,...]]`
   311  
   312  See each command's section for contextual examples of the `--where` flag filter usage.
   313  
   314  ---
   315  
   316  ### Validate
   317  
   318  This command will parse standardized SBOMs and validate it against its declared format and version (e.g., SPDX 2.3, CycloneDX 1.6). Custom  variants of standard JSON schemas can be used for validation by supplying the `--variant` name as a flag. Explicit JSON schemas can be specified using the `--force` flag.
   319  
   320  #### Validating using supported schemas
   321  
   322  Use the [schema](#schema) command to list supported schemas formats, versions and variants.
   323  
   324  #### Validating using "custom" schemas
   325  
   326  Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file. See [adding schemas](#adding-schemas).
   327  
   328  - **"Customized" schema** variants, perhaps derived from standard BOM schemas, can be used for validation using the `--variant` flag (e.g., industry or company-specific schemas).
   329  - **Overriding default schema** - You can override an BOM's declared BOM version using the `--force` flag (e.g., verify a BOM against a newer specification version).
   330  
   331  #### Validate flags
   332  
   333  The following flags can be used to improve performance when formatting error output results:
   334  
   335  ##### `--error-limit` flag
   336  
   337  Use the `--error-limit x` (default: `10`) flag to reduce the formatted error result output to the first `x` errors.  By default, only the first 10 errors are output with an informational messaging indicating `x/y` errors were shown.
   338  
   339  ##### `--error-value` flag
   340  
   341  Use the `--error-value=true|false` (default: `true`) flag to reduce the formatted error result output by not showing the `value` field which shows detailed information about the failing data in the BOM.
   342  
   343  ##### `--colorize` flag
   344  
   345  Use the `--colorize=true|false` (default: `false`) flag to add/remove color formatting to error result `txt` formatted output.  By default, `txt` formatted error output is colorized to help with human readability; for automated use, it can be turned off.
   346  
   347  #### Validate Examples
   348  
   349  ##### Example: Validate using inferred format and schema
   350  
   351  Validating the "juice shop" SBOM (CycloneDX 1.2) example provided in this repository.
   352  
   353  ```bash
   354  ./sbom-utility validate -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json
   355  ```
   356  
   357  ```bash
   358  [INFO] Loading (embedded) default schema config file: `config.json`...
   359  [INFO] Loading (embedded) default license policy file: `license.json`...
   360  [INFO] Attempting to load and unmarshal data from: `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json`...
   361  [INFO] Successfully unmarshalled data from: `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json`
   362  [INFO] Determining file's BOM format and version...
   363  [INFO] Determined BOM format, version (variant): `CycloneDX`, `1.2` (latest)
   364  [INFO] Matching BOM schema (for validation): schema/cyclonedx/1.2/bom-1.2.schema.json
   365  [INFO] Loading schema `schema/cyclonedx/1.2/bom-1.2.schema.json`...
   366  [INFO] Schema `schema/cyclonedx/1.2/bom-1.2.schema.json` loaded.
   367  [INFO] Validating `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json`...
   368  [INFO] BOM valid against JSON schema: `true`
   369  ```
   370  
   371  You can also verify the [exit code](#exit-codes) from the validate command:
   372  
   373  ```bash
   374  echo $?
   375  ```
   376  
   377  ```bash
   378  0  // no error (valid)
   379  ```
   380  
   381  #### Example: Validate using "custom" schema variants
   382  
   383  The validation command will use the declared format and version found within the SBOM JSON file itself to lookup the default (latest) matching schema version (as declared in`config.json`; however, if variants of that same schema (same format and version) are declared, they can be requested via the `--variant` command line flag:
   384  
   385  ```bash
   386  ./sbom-utility validate -i test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json --variant custom
   387  ```
   388  
   389  If you run the sample command above, you would see several "custom" schema errors resulting in an invalid SBOM determination (i.e., `exit status 2`):
   390  
   391  ```text
   392  [INFO] Loading (embedded) default schema config file: `config.json`...
   393  [INFO] Loading (embedded) default license policy file: `license.json`...
   394  [INFO] Attempting to load and unmarshal data from: `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`...
   395  [INFO] Successfully unmarshalled data from: `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`
   396  [INFO] Determining file's BOM format and version...
   397  [INFO] Determined BOM format, version (variant): `CycloneDX`, `1.4` custom
   398  [INFO] Matching BOM schema (for validation): schema/test/bom-1.4-custom.schema.json
   399  [INFO] Loading schema `schema/test/bom-1.4-custom.schema.json`...
   400  [INFO] Schema `schema/test/bom-1.4-custom.schema.json` loaded.
   401  [INFO] Validating `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`...
   402  [INFO] BOM valid against JSON schema: `false`
   403  [INFO] (3) schema errors detected.
   404  [INFO] Formatting error results (`txt` format)...
   405  1. {
   406          "type": "contains",
   407          "field": "metadata.properties",
   408          "context": "(root).metadata.properties",
   409          "description": "At least one of the items must match",
   410          "value": [
   411              {
   412                  "name": "urn:example.com:disclaimer",
   413                  "value": "This SBOM is current as of the date it was generated."
   414              },
   415              {
   416                  "name": "urn:example.com:classification",
   417                  "value": "This SBOM is Confidential Information. Do not distribute."
   418              }
   419          ]
   420      }
   421  2. {
   422          "type": "const",
   423          "field": "metadata.properties.0.value",
   424          "context": "(root).metadata.properties.0.value",
   425          "description": "metadata.properties.0.value does not match: \"This SBOM is current as of the date it was generated and is subject to change.\"",
   426          "value": "This SBOM is current as of the date it was generated."
   427      }
   428  3. {
   429          "type": "number_all_of",
   430          "field": "metadata.properties",
   431          "context": "(root).metadata.properties",
   432          "description": "Must validate all the schemas (allOf)",
   433          "value": [
   434              {
   435                  "name": "urn:example.com:disclaimer",
   436                  "value": "This SBOM is current as of the date it was generated."
   437              },
   438              {
   439                  "name": "urn:example.com:classification",
   440                  "value": "This SBOM is Confidential Information. Do not distribute."
   441              }
   442          ]
   443      }
   444  [ERROR] invalid SBOM: schema errors found (test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json)
   445  [INFO] document `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`: valid=[false]
   446  ```
   447  
   448  confirming the exit code:
   449  
   450  ```bash
   451  echo $?
   452  ```
   453  
   454  ```bash
   455  2 // SBOM error
   456  ```
   457  
   458  ##### Why validation failed
   459  
   460  The output shows a first schema error indicating the failing JSON object; in this case,
   461  
   462  - the CycloneDX `metadata.properties` field, which is a list of `property` objects.
   463  - Found that a property with a `name` field with the value  `"urn:example.com:disclaimer"` had an incorrect `value`.
   464    - the `value` field SHOULD have had a constant value of `"This SBOM is current as of the date it was generated and is subject to change."` (as was required by the custom schema's regex).
   465    - However, it was found to have only a partial match of `"This SBOM is current as of the date it was generated."`.
   466  
   467  ##### Details of the schema error
   468  
   469  Use the `--debug` or `-d` flag to see all schema error details:
   470  
   471  ```bash
   472  ./sbom-utility validate -i test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json --variant custom -d
   473  ```
   474  
   475  The details include the full context of the failing `metadata.properties` object which also includes a `"urn:example.com:classification"` property:
   476  
   477  ```bash
   478  3. {
   479          "type": "number_all_of",
   480          "field": "metadata.properties",
   481          "context": "(root).metadata.properties",
   482          "description": "Must validate all the schemas (allOf)",
   483          "value": [
   484              {
   485                  "name": "urn:example.com:disclaimer",
   486                  "value": "This SBOM is current as of the date it was generated."
   487              },
   488              {
   489                  "name": "urn:example.com:classification",
   490                  "value": "This SBOM is Confidential Information. Do not distribute."
   491              }
   492          ]
   493      }
   494  ```
   495  
   496  #### Example: Validate using "JSON" format
   497  
   498  The JSON format will provide an `array` of schema error results that can be post-processed as part of validation toolchain.
   499  
   500  ```bash
   501  ./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json -q
   502  ```
   503  
   504  ```json
   505  [
   506      {
   507          "type": "unique",
   508          "field": "components",
   509          "context": "(root).components",
   510          "description": "array items[1,2] must be unique",
   511          "value": {
   512              "type": "array",
   513              "index": 1,
   514              "item": {
   515                  "bom-ref": "pkg:npm/body-parser@1.19.0",
   516                  "description": "Node.js body parsing middleware",
   517                  "hashes": [
   518                      {
   519                          "alg": "SHA-1",
   520                          "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   521                      }
   522                  ],
   523                  "licenses": [
   524                      {
   525                          "license": {
   526                              "id": "MIT"
   527                          }
   528                      }
   529                  ],
   530                  "name": "body-parser",
   531                  "purl": "pkg:npm/body-parser@1.19.0",
   532                  "type": "library",
   533                  "version": "1.19.0"
   534              }
   535          }
   536      },
   537      {
   538          "type": "unique",
   539          "field": "components",
   540          "context": "(root).components",
   541          "description": "array items[2,4] must be unique",
   542          "value": {
   543              "type": "array",
   544              "index": 2,
   545              "item": {
   546                  "bom-ref": "pkg:npm/body-parser@1.19.0",
   547                  "description": "Node.js body parsing middleware",
   548                  "hashes": [
   549                      {
   550                          "alg": "SHA-1",
   551                          "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   552                      }
   553                  ],
   554                  "licenses": [
   555                      {
   556                          "license": {
   557                              "id": "MIT"
   558                          }
   559                      }
   560                  ],
   561                  "name": "body-parser",
   562                  "purl": "pkg:npm/body-parser@1.19.0",
   563                  "type": "library",
   564                  "version": "1.19.0"
   565              }
   566          }
   567      }
   568  ]
   569  ```
   570  
   571  ##### Reducing output size using `error-value=false` flag
   572  
   573  In many cases, BOMs may have many errors and having the `value` information details included can be too verbose and lead to large output files to inspect.  In those cases, simply set the `error-value` flag to `false`.
   574  
   575  Rerunning the same command with this flag set to false yields a reduced set of information.
   576  
   577  ```bash
   578  ./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json --error-value=false -q
   579  ```
   580  
   581  ```json
   582  [
   583      {
   584          "type": "unique",
   585          "field": "components",
   586          "context": "(root).components",
   587          "description": "array items[1,2] must be unique"
   588      },
   589      {
   590          "type": "unique",
   591          "field": "components",
   592          "context": "(root).components",
   593          "description": "array items[2,4] must be unique"
   594      }
   595  ]
   596  ```
   597  
   598  ---
   599  
   600  ### Trim
   601  
   602  This command is able to "trim" one or more JSON keys (fields) from specified JSON BOM documents effectively "pruning" the JSON document.  This functionality helps consumers of large-sized BOMs that need to analyze specific types of data in large BOMs in reducing the BOM data to just what is needed for their use cases or needs.
   603  
   604  #### Trim supported output formats
   605  
   606  This command is used to output, using the [`--output-file` flag](#output-flag), a "trimmed" BOM in JSON format.
   607  
   608  - `json` (default)
   609  
   610  #### Trim flags
   611  
   612  Trim operates on a JSON BOM input file (see [`--input-file` flag](#input-flag)) and produces a trimmed JSON BOM output file using the following flags:
   613  
   614  ##### Trim `--keys` flag
   615  
   616  A comma-separated list of JSON map keys. Similar to the [query command's `--select` flag](#query---select-flag) syntax.
   617  
   618  ##### Trim `--from` flag
   619  
   620  A comma-separated list of JSON document paths using the same syntax as the [query command's `--from` flag](#query---from-flag).
   621  
   622  ##### Trim `--normalize` flag
   623  
   624  A flag that normalizes the BOM data after trimming and prior to output.
   625  
   626  This flag has custom code that sorts all components, services, licenses, vulnerabilities, properties, external references, hashes and *most* other BOM data using custom comparators.
   627  
   628  Each comparator uses `required` fields and other identifying fields to create *"composite keys"* for each unique data structure.
   629  
   630  #### Trim examples
   631  
   632  The original BOM used for these examples can be found here:
   633  
   634  - [test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json](test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json)
   635  
   636  ##### Example: Trim `properties` from entire JSON BOM
   637  
   638  Validating the "juice shop" SBOM (CycloneDX 1.2) example provided in this repository.
   639  
   640  ```bash
   641  ./sbom-utility trim -i ./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=properties
   642  ```
   643  
   644  Original BOM with `properties`:
   645  
   646  ```json
   647  {
   648    "bomFormat": "CycloneDX",
   649    "specVersion": "1.5",
   650    "version": 1,
   651    "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9",
   652    "components": [
   653      {
   654        "type": "library",
   655        "bom-ref": "pkg:npm/sample@2.0.0",
   656        "purl": "pkg:npm/sample@2.0.0",
   657        "name": "sample",
   658        "version": "2.0.0",
   659        "description": "Node.js Sampler package",
   660        "properties": [
   661          {
   662            "name": "foo",
   663            "value": "bar"
   664          }
   665        ]
   666      },
   667      {
   668        "type": "library",
   669        "bom-ref": "pkg:npm/body-parser@1.19.0",
   670        "purl": "pkg:npm/body-parser@1.19.0",
   671        "name": "body-parser",
   672        "version": "1.19.0",
   673        "description": "Node.js body parsing middleware",
   674        "hashes": [
   675          {
   676            "alg": "SHA-1",
   677            "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   678          }
   679        ]
   680      }
   681    ],
   682    "properties": [
   683      {
   684        "name": "abc",
   685        "value": "123"
   686      }
   687    ]
   688  }
   689  ```
   690  
   691  Output BOM results without `properties`:
   692  
   693  ```json
   694  {
   695      "bomFormat": "CycloneDX",
   696      "specVersion": "1.5",
   697      "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9",
   698      "version": 1,
   699      "components": [
   700          {
   701              "type": "library",
   702              "bom-ref": "pkg:npm/sample@2.0.0",
   703              "name": "sample",
   704              "version": "2.0.0",
   705              "description": "Node.js Sampler package",
   706              "purl": "pkg:npm/sample@2.0.0"
   707          },
   708          {
   709              "type": "library",
   710              "bom-ref": "pkg:npm/body-parser@1.19.0",
   711              "name": "body-parser",
   712              "version": "1.19.0",
   713              "description": "Node.js body parsing middleware",
   714              "hashes": [
   715                  {
   716                      "alg": "SHA-1",
   717                      "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   718                  }
   719              ],
   720              "purl": "pkg:npm/body-parser@1.19.0"
   721          }
   722      ]
   723  }
   724  ```
   725  
   726  ##### Example: Trim `name` and `description` from entire JSON BOM
   727  
   728  ```bash
   729  ./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=name,description -q
   730  ```
   731  
   732  Output BOM results without `name` or `description`:
   733  
   734  ```json
   735  {
   736      "bomFormat": "CycloneDX",
   737      "specVersion": "1.5",
   738      "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9",
   739      "version": 1,
   740      "components": [
   741          {
   742              "type": "library",
   743              "bom-ref": "pkg:npm/sample@2.0.0",
   744              "version": "2.0.0",
   745              "purl": "pkg:npm/sample@2.0.0",
   746              "properties": [
   747                  {
   748                      "value": "bar"
   749                  }
   750              ]
   751          },
   752          {
   753              "type": "library",
   754              "bom-ref": "pkg:npm/body-parser@1.19.0",
   755              "version": "1.19.0",
   756              "hashes": [
   757                  {
   758                      "alg": "SHA-1",
   759                      "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   760                  }
   761              ],
   762              "purl": "pkg:npm/body-parser@1.19.0"
   763          }
   764      ],
   765      "properties": [
   766          {
   767              "value": "123"
   768          }
   769      ]
   770  }
   771  ```
   772  
   773  ##### Example: Trim `properties` from only `components` path
   774  
   775  ```bash
   776  ./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=properties --from components -q
   777  ```
   778  
   779  Output BOM results with `properties` removed from all `components`:
   780  
   781  ```json
   782  {
   783      "bomFormat": "CycloneDX",
   784      "specVersion": "1.5",
   785      "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9",
   786      "version": 1,
   787      "components": [
   788          {
   789              "type": "library",
   790              "bom-ref": "pkg:npm/sample@2.0.0",
   791              "name": "sample",
   792              "version": "2.0.0",
   793              "description": "Node.js Sampler package",
   794              "purl": "pkg:npm/sample@2.0.0"
   795          },
   796          {
   797              "type": "library",
   798              "bom-ref": "pkg:npm/body-parser@1.19.0",
   799              "name": "body-parser",
   800              "version": "1.19.0",
   801              "description": "Node.js body parsing middleware",
   802              "hashes": [
   803                  {
   804                      "alg": "SHA-1",
   805                      "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   806                  }
   807              ],
   808              "purl": "pkg:npm/body-parser@1.19.0"
   809          }
   810      ],
   811      "properties": [
   812          {
   813              "name": "abc",
   814              "value": "123"
   815          }
   816      ]
   817  }
   818  ```
   819  
   820  ---
   821  
   822  ##### Example: Trim `bom-ref` and normalize output
   823  
   824  ```bash
   825  ./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-components-normalize.sbom.json --keys="bom-ref" --normalize -q
   826  ```
   827  
   828  **Note** If you do not want to remove any keys and simply normalize output, set keys to an empty string: `--keys=""`.
   829  
   830  Use the trim command to remove all `bom-ref` fields and normalize output:
   831  
   832  ```json
   833  {
   834    "bomFormat": "CycloneDX",
   835    "specVersion": "1.5",
   836    "components": [
   837      {
   838        "type": "library",
   839        "bom-ref": "pkg:npm/sample@2.0.0",
   840        "purl": "pkg:npm/sample@2.0.0",
   841        "name": "sample",
   842        "version": "2.0.0",
   843        "licenses": [
   844          {
   845            "license": {
   846              "id": "GPL-2.0-or-later"
   847            }
   848          },
   849          {
   850            "license": {
   851              "id": "LGPL-2.0-or-later"
   852            }
   853          },
   854          {
   855            "license": {
   856              "id": "GPL-2.0-only"
   857            }
   858          }
   859        ],
   860        "properties": [
   861          {
   862            "name": "moo",
   863            "value": "cow"
   864          },
   865          {
   866            "name": "foo",
   867            "value": "bar"
   868          }
   869        ]
   870      },
   871      {
   872        "type": "library",
   873        "bom-ref": "pkg:npm/body-parser@1.19.0",
   874        "purl": "pkg:npm/body-parser@1.19.0",
   875        "name": "body-parser",
   876        "version": "1.19.0",
   877        "hashes": [
   878          {
   879            "alg": "SHA-256",
   880            "content": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
   881          },
   882          {
   883            "alg": "SHA-1",
   884            "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   885          }
   886        ],
   887        "licenses": [
   888          {
   889            "license": {
   890              "id": "MIT"
   891            }
   892          },
   893          {
   894            "license": {
   895              "id": "Apache-2.0"
   896            }
   897          }
   898        ],
   899        "externalReferences": [
   900          {
   901            "type": "website",
   902            "url": "https://example.com/website"
   903          },
   904          {
   905            "type": "support",
   906            "url": "https://example.com/support"
   907          }
   908        ]
   909      }
   910    ]
   911  }
   912  ```
   913  
   914  Trimmed, normalized output:
   915  
   916  ```json
   917  {
   918    "bomFormat": "CycloneDX",
   919    "specVersion": "1.5",
   920    "components": [
   921      {
   922        "type": "library",
   923        "name": "body-parser",
   924        "version": "1.19.0",
   925        "hashes": [
   926          {
   927            "alg": "SHA-1",
   928            "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   929          },
   930          {
   931            "alg": "SHA-256",
   932            "content": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
   933          }
   934        ],
   935        "licenses": [
   936          {
   937            "license": {
   938              "id": "Apache-2.0"
   939            }
   940          },
   941          {
   942            "license": {
   943              "id": "MIT"
   944            }
   945          }
   946        ],
   947        "purl": "pkg:npm/body-parser@1.19.0",
   948        "externalReferences": [
   949          {
   950            "type": "support",
   951            "url": "https://example.com/support"
   952          },
   953          {
   954            "type": "website",
   955            "url": "https://example.com/website"
   956          }
   957        ]
   958      },
   959      {
   960        "type": "library",
   961        "name": "sample",
   962        "version": "2.0.0",
   963        "licenses": [
   964          {
   965            "license": {
   966              "id": "GPL-2.0-only"
   967            }
   968          },
   969          {
   970            "license": {
   971              "id": "GPL-2.0-or-later"
   972            }
   973          },
   974          {
   975            "license": {
   976              "id": "LGPL-2.0-or-later"
   977            }
   978          }
   979        ],
   980        "purl": "pkg:npm/sample@2.0.0",
   981        "properties": [
   982          {
   983            "name": "foo",
   984            "value": "bar"
   985          },
   986          {
   987            "name": "moo",
   988            "value": "cow"
   989          }
   990        ]
   991      }
   992    ]
   993  }
   994  ```
   995  
   996  ---
   997  
   998  ### Patch
   999  
  1000  This *experimental* command is able to "patch" an existing JSON BOM document using an [IETF RFC6902](https://datatracker.ietf.org/doc/html/rfc6902/#section-4.1) *"JavaScript Object Notation (JSON) Patch"* file.
  1001  
  1002  The current implementation supports the following "patch" operations:
  1003  
  1004  - "add", "update", "remove" and "test"
  1005  
  1006  At this time the "move" or "copy" operations are not supported.
  1007  
  1008  Patches work for both simple (i.e., integer, float, boolean and string) values as well as complex values such as JSON objects, maps and arrays.
  1009  
  1010  #### Patch supported output formats
  1011  
  1012  This command is used to output, using the [`--output-file` flag](#output-flag), a "patched" BOM in JSON format.
  1013  
  1014  - `json` (default)
  1015  
  1016  #### Patch flags
  1017  
  1018  The patch command operates on a JSON BOM input file (see [`--input-file` flag](#input-flag)) as well as an [IETF RFC6902](https://datatracker.ietf.org/doc/html/rfc6902/#section-4.1)-formatted "patch' file and produces a "patched" version of the input JSON BOM as output using the following flags:
  1019  
  1020  ##### Patch `--patch-filename` flag
  1021  
  1022  The `--patch-file <filename>` flag is used to provide the relative path to the IETF RFC6902 patch file to applied to the BOM input file.
  1023  
  1024  #### Patch examples
  1025  
  1026  This section contains examples of all supported patch operations (i.e., add, replace, test) including values that are primitives (i.e., `numbers`, `strings`) as well as JSON `objects` and may be indexed JSON `array` elements.
  1027  
  1028  - ["add" BOM `serialNumber`](#patch-example-1-add-bom-serialnumber)
  1029  - ["add" (update) BOM `version`](#patch-example-2-add-update-bom-version)
  1030  - ["add" `supplier` object to `metadata`](#patch-example-3-add-supplier-object-to-metadata-object)
  1031  - ["add" `property` objects to `metadata.properties` array](#patch-example-4-add-property-objects-to-metadataproperties-array)
  1032  - ["replace" `version` and `timestamp` values](#patch-example-5-replace-bom-version-and-timestamp)
  1033  - ["remove" `property` from the `metadata.properties` array](#patch-example-6-remove-property-from-the-metadataproperties-array)
  1034  - ["test" if a `property` exists in the `metadata.properties` array](#patch-example-7-test-property-exists-in-the-metadataproperties-array)
  1035  
  1036  ##### Patch example 1: "add" BOM `serialNumber`
  1037  
  1038  This example adds a new top-level key `"serialNumber"` and corresponding value to a CycloneDX JSON BOM file.
  1039  
  1040  The original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json) has no serial number:
  1041  
  1042  ```json
  1043  {
  1044    "bomFormat": "CycloneDX",
  1045    "specVersion": "1.5",
  1046    "version": 1,
  1047    "metadata": {
  1048        ...
  1049    }
  1050  }
  1051  ```
  1052  
  1053  IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-serial-number.json](test/patch/cdx-patch-example-add-serial-number.json):
  1054  
  1055  ```json
  1056  [
  1057    { "op": "add", "path": "/serialNumber", "value": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9" }
  1058  ]
  1059  ```
  1060  
  1061  Invoke the patch command as follows:
  1062  
  1063  ```bash
  1064  ./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-serial-number.json -q
  1065  ```
  1066  
  1067  Patched JSON BOM output file:
  1068  
  1069  ```json
  1070  {
  1071      "bomFormat": "CycloneDX",
  1072      "specVersion": "1.5",
  1073      "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9",
  1074      "version": 1,
  1075      "metadata": {
  1076          ...
  1077      }
  1078  }
  1079  ```
  1080  
  1081  ##### Patch example 2: "add" (update) BOM `version`
  1082  
  1083  This example shows how the patch's "add" operation can be used to update existing values which is the specified behavior of RFC6902.
  1084  
  1085  Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json) with `version` equal to `1`:
  1086  
  1087  ```json
  1088  {
  1089    "bomFormat": "CycloneDX",
  1090    "specVersion": "1.5",
  1091    "version": 1,
  1092    "metadata": {
  1093        ...
  1094    }
  1095  }
  1096  ```
  1097  
  1098  IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-serial-number.json](test/patch/cdx-patch-example-add-serial-number.json):
  1099  
  1100  ```json
  1101  [
  1102    { "op": "add", "path": "/version", "value": 2 }
  1103  ]
  1104  ```
  1105  
  1106  Invoke the patch command as follows:
  1107  
  1108  ```bash
  1109  ./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-update-version.json -q
  1110  ```
  1111  
  1112  The patched, output JSON BOM file which has the changed `version` value of `2`:
  1113  
  1114  ```json
  1115  {
  1116      "bomFormat": "CycloneDX",
  1117      "specVersion": "1.5",
  1118      "version": 2,
  1119      "metadata": {
  1120          ...
  1121      }
  1122  }
  1123  ```
  1124  
  1125  ##### Patch example 3: "add" `supplier` object to `metadata` object
  1126  
  1127  This example shows how the patch's "add" operation can be used to add a JSON object to an existing object.
  1128  
  1129  Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json):
  1130  
  1131  ```json
  1132  {
  1133    "bomFormat": "CycloneDX",
  1134    "specVersion": "1.5",
  1135    "version": 1,
  1136    "metadata": {
  1137      "timestamp": "2023-10-12T19:07:00Z",
  1138      "properties": [
  1139        ...
  1140      ]
  1141    }
  1142  }
  1143  ```
  1144  
  1145  Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-metadata-supplier.json](test/patch/cdx-patch-example-add-metadata-supplier.json):
  1146  
  1147  ```json
  1148  [
  1149    { "op": "add", "path": "/metadata/supplier", "value": {
  1150        "name": "Example Co. Distribution Dept.",
  1151        "url": [
  1152          "https://example.com/software/"
  1153        ]
  1154      }
  1155    }
  1156  ]
  1157  ```
  1158  
  1159  Invoke the patch command as follows:
  1160  
  1161  ```bash
  1162  ./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-metadata-supplier.json -q
  1163  ```
  1164  
  1165  The patched BOM has the `supplier` object added to the `metadata`:
  1166  
  1167  ```json
  1168  {
  1169      "bomFormat": "CycloneDX",
  1170      "specVersion": "1.5",
  1171      "version": 1,
  1172      "metadata": {
  1173          "timestamp": "2023-10-12T19:07:00Z",
  1174          "supplier": {
  1175              "name": "Example Co. Distribution Dept.",
  1176              "url": [
  1177                  "https://example.com/software/"
  1178              ]
  1179          },
  1180          "properties": [
  1181              ...
  1182          ]
  1183      }
  1184  }
  1185  ```
  1186  
  1187  ##### Patch example 4: "add" `property` objects to `metadata.properties` array
  1188  
  1189  This example shows how the patch's "add" operation can be used to add `property` objects to an existing `properties` array.
  1190  
  1191  Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json):
  1192  
  1193  ```json
  1194  {
  1195    "bomFormat": "CycloneDX",
  1196    "specVersion": "1.5",
  1197    "version": 1,
  1198    "metadata": {
  1199      "timestamp": "2023-10-12T19:07:00Z",
  1200      "properties": [
  1201        {
  1202          "name": "Property 1",
  1203          "value": "Value 1"
  1204        },
  1205        {
  1206          "name": "Property 2",
  1207          "value": "Value 2"
  1208        }
  1209      ]
  1210    }
  1211  }
  1212  ```
  1213  
  1214  Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-metadata-properties.json](test/patch/cdx-patch-example-add-metadata-properties.json):
  1215  
  1216  ```json
  1217  [
  1218    { "op": "add", "path": "/metadata/properties/-", "value": { "name": "foo", "value": "bar" } },
  1219    { "op": "add", "path": "/metadata/properties/1", "value": { "name": "rush", "value": "yyz" } }
  1220  ]
  1221  ```
  1222  
  1223  Note that the first patch record uses the `-` (dash) to indicate "insert at end" whereas the second patch record has the zero-based array index `1`.
  1224  
  1225  Invoke the patch command as follows:
  1226  
  1227  ```bash
  1228  ./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-metadata-properties.json -q
  1229  ```
  1230  
  1231  The patched, output BOM has the two new properties at the specified indices:
  1232  
  1233  ```json
  1234  {
  1235      "bomFormat": "CycloneDX",
  1236      "specVersion": "1.5",
  1237      "version": 1,
  1238      "metadata": {
  1239          "timestamp": "2023-10-12T19:07:00Z",
  1240          "properties": [
  1241              {
  1242                  "name": "Property 1",
  1243                  "value": "Value 1"
  1244              },
  1245              {
  1246                  "name": "rush",
  1247                  "value": "yyz"
  1248              },
  1249              {
  1250                  "name": "Property 2",
  1251                  "value": "Value 2"
  1252              },
  1253              {
  1254                  "name": "foo",
  1255                  "value": "bar"
  1256              }
  1257          ]
  1258      }
  1259  }
  1260  ```
  1261  
  1262  ##### Patch example 5: "replace" BOM `version` and `timestamp`
  1263  
  1264  This example shows how the patch's "replace" operation can be used to update the BOM document's `version` and `timestamp` values.
  1265  
  1266  Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json):
  1267  
  1268  ```json
  1269  {
  1270    "bomFormat": "CycloneDX",
  1271    "specVersion": "1.5",
  1272    "version": 1,
  1273    "metadata": {
  1274      "timestamp": "2023-10-12T19:07:00Z",
  1275      "properties": [
  1276        ...
  1277      ]
  1278    }
  1279  }
  1280  ```
  1281  
  1282  Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-replace-version-timestamp.json](test/patch/cdx-patch-example-replace-version-timestamp.json):
  1283  
  1284  ```json
  1285  [
  1286    { "op": "replace", "path": "/version", "value": 2 },
  1287    { "op": "replace", "path": "/metadata/timestamp", "value": "2024-01-24T22:50:18+00:00" }
  1288  ]
  1289  ```
  1290  
  1291  Invoke the patch command as follows:
  1292  
  1293  ```bash
  1294  ./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-replace-version-timestamp.json -q
  1295  ```
  1296  
  1297  The patched, output BOM has both an updated `version` and `timestamp`:
  1298  
  1299  ```json
  1300  {
  1301      "bomFormat": "CycloneDX",
  1302      "specVersion": "1.5",
  1303      "version": 2,
  1304      "metadata": {
  1305          "timestamp": "2024-01-24T22:50:18+00:00",
  1306          "properties": [
  1307            ...
  1308      }
  1309  }
  1310  ```
  1311  
  1312  ##### Patch example 6: "remove" `property` from the `metadata.properties` array
  1313  
  1314  This example shows how the patch's "remove" operation can be used to remove a `property` object from the `metadata.properties` array using an index.
  1315  
  1316  Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json):
  1317  
  1318  ```json
  1319  {
  1320    "bomFormat": "CycloneDX",
  1321    "specVersion": "1.5",
  1322    "version": 1,
  1323    "metadata": {
  1324      "timestamp": "2023-10-12T19:07:00Z",
  1325      "properties": [
  1326        {
  1327          "name": "Property 1",
  1328          "value": "Value 1"
  1329        },
  1330        {
  1331          "name": "Property 2",
  1332          "value": "Value 2"
  1333        }
  1334      ]
  1335    }
  1336  }
  1337  ```
  1338  
  1339  Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-remove-metadata-property.json](test/patch/cdx-patch-example-remove-metadata-property.json):
  1340  
  1341  ```json
  1342  [
  1343    { "op": "remove", "path": "/metadata/properties/1" }
  1344  ]
  1345  ```
  1346  
  1347  Invoke the patch command as follows:
  1348  
  1349  ```bash
  1350  ./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-remove-metadata-property.json -q
  1351  ```
  1352  
  1353  The `property` at index `1` of the `metadata.properties` array has been removed:
  1354  
  1355  ```json
  1356  {
  1357      "bomFormat": "CycloneDX",
  1358      "specVersion": "1.5",
  1359      "version": 1,
  1360      "metadata": {
  1361          "timestamp": "2023-10-12T19:07:00Z",
  1362          "properties": [
  1363              {
  1364                  "name": "Property 1",
  1365                  "value": "Value 1"
  1366              }
  1367          ]
  1368      }
  1369  }
  1370  ```
  1371  
  1372  ##### Patch example 7: "test" `property` exists in the `metadata.properties` array
  1373  
  1374  This example shows how the patch records's can "test" for values or objects in a BOM.  The utility will confirm "success" (using an `[INFO]` log message); otherwise, the utility will exit and return an error and generate an `[ERROR]` log message.
  1375  
  1376  Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json):
  1377  
  1378  ```json
  1379  {
  1380    "bomFormat": "CycloneDX",
  1381    "specVersion": "1.5",
  1382    "version": 1,
  1383    "metadata": {
  1384      "timestamp": "2023-10-12T19:07:00Z",
  1385      "properties": [
  1386        {
  1387          "name": "Property 1",
  1388          "value": "Value 1"
  1389        },
  1390        {
  1391          "name": "Property 2",
  1392          "value": "Value 2"
  1393        }
  1394      ]
  1395    }
  1396  }
  1397  ```
  1398  
  1399  Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-test-metadata-property.json](test/patch/cdx-patch-example-test-metadata-property.json):
  1400  
  1401  ```json
  1402  [
  1403    { "op": "test", "path": "/metadata/properties/1", "value":
  1404      {
  1405        "name": "Property 2",
  1406        "value": "Value 2"
  1407      }
  1408    }
  1409  ]
  1410  ```
  1411  
  1412  Invoke the patch command as follows:
  1413  
  1414  ```bash
  1415  ./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-test-metadata-property.json -q
  1416  ```
  1417  
  1418  An informational (i.e., `[INFO]`) message is logged with `success` since the property object was found in the input BOM:
  1419  
  1420  ```json
  1421  [INFO] IETF RFC6902 test operation success. test record: {
  1422      "op": "test",
  1423      "path": "/metadata/properties/1",
  1424      "value": {
  1425          "name": "Property 2",
  1426          "value": "Value 2"
  1427      }
  1428  }
  1429  ```
  1430  
  1431  If instead, we [tested for a different property](test/patch/cdx-patch-example-test-metadata-property-err.json) object:
  1432  
  1433  ```json
  1434  [
  1435    { "op": "test", "path": "/metadata/properties/1", "value":
  1436      {
  1437        "name": "Property 3",
  1438        "value": "Value 3"
  1439      }
  1440    }
  1441  ]
  1442  ```
  1443  
  1444  an error (i.e., `[ERROR]`) would be returned from the utility:
  1445  
  1446  ```json
  1447  [ERROR] IETF RFC6902 test operation error. test record: {
  1448      "op": "test",
  1449      "path": "/metadata/properties/1",
  1450      "value": {
  1451          "name": "Property 3",
  1452          "value": "Value 3"
  1453      }
  1454  }
  1455  ```
  1456  
  1457  ---
  1458  
  1459  ### Query
  1460  
  1461  This command allows you to perform SQL-like queries into JSON format SBOMs.  Currently, the command recognizes the `--select` and `--from` as well as the `--where` filter.
  1462  
  1463  #### Query flags
  1464  
  1465  ##### Query `--from` flag
  1466  
  1467  The `--from` clause value is applied to the JSON document object model and can return either a singleton JSON object or an array of JSON objects as a result.  This is determined by the last property value's type as declared in the schema.
  1468  
  1469  ##### Query `--select` flag
  1470  
  1471  The `--select` clause is then applied to the `--from` result set to only return the specified properties (names and their values).
  1472  
  1473  ##### Query `--where` flag
  1474  
  1475  If the result set is an array, the array entries can be reduced by applying the `--where` filter to ony return those entries whose specified field names match the supplied regular expression (regex).
  1476  
  1477  **Note**: All `query` command results are returned as valid JSON documents.  This includes a `null` value for empty result sets.
  1478  
  1479  #### Query supported formats
  1480  
  1481  The `query` command only supports JSON output.
  1482  
  1483  - `json` (default)
  1484  
  1485  #### Query result sorting
  1486  
  1487  The `query` command does not support formatting of output results as JSON format is always returned.
  1488  
  1489  #### Query examples
  1490  
  1491  ##### Example: Extract the top-level `component` information from an SBOM
  1492  
  1493  This example effectively extracts the first-order package manifest from the SBOM.
  1494  
  1495  In this example, only the `--from` clause is needed to select an object.  The `--select` clause is omitted which is equivalent to using the "select all" wildcard character `*` which returns all fields and values from the `component` object.
  1496  
  1497  ```bash
  1498  ./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from metadata.component
  1499  ```
  1500  
  1501  is equivalent to using the wildcard character (which may need to be enclosed in single or double quotes depending on your shell):
  1502  
  1503  ```bash
  1504  ./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --select '*' --from metadata.component -q
  1505  ```
  1506  
  1507  ```json
  1508  {
  1509    "name": "Example Application v10.0.4",
  1510    "bom-ref": "pkg:oci/example.com/product/application@10.0.4.0",
  1511    "description": "Example's Do-It-All application",
  1512    "externalReferences": [
  1513      {
  1514        "type": "website",
  1515        "url": "https://example.com/application"
  1516      }
  1517    ],
  1518    "hashes": [
  1519      {
  1520        "alg": "SHA-1",
  1521        "content": "1111aaaa2222cccc3333dddd4444eeee5555ffff"
  1522      }
  1523    ],
  1524    "licenses": [
  1525      {
  1526        "license": {
  1527          "id": "Apache-2.0"
  1528        }
  1529      }
  1530    ],
  1531    ...
  1532  ```
  1533  
  1534  ##### Example: Extract the `supplier` of the SBOM
  1535  
  1536  In this example, the `--from` clause references the top-level `metadata.supplier` object.
  1537  
  1538  ```bash
  1539  ./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from metadata.supplier -q
  1540  ```
  1541  
  1542  ```json
  1543  {
  1544    "contact": [
  1545      {
  1546        "email": "distribution@example.com"
  1547      }
  1548    ],
  1549    "name": "Example Co. Distribution Dept.",
  1550    "url": [
  1551      "https://example.com/software/"
  1552    ]
  1553  }
  1554  ```
  1555  
  1556  ##### Example: Extract just the SBOM component's `name` and `version`
  1557  
  1558  In this example, the `--from` clause references the singleton JSON object `component` found under the top-level `metadata` object. It then reduces the resultant JSON object to only return the `name` and `value` fields and their values as requested on the `--select` clause.
  1559  
  1560  ```bash
  1561  ./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --indent 2 -q
  1562  ```
  1563  
  1564  The result, which also uses the `--indent 2` flag:
  1565  
  1566  ```json
  1567  {
  1568    "name": "juice-shop",
  1569    "version": "11.1.2"
  1570  }
  1571  ```
  1572  
  1573  ##### Example: Return the JSON array of components
  1574  
  1575  In this example, the `--from` filter will return the entire JSON components array.
  1576  
  1577  ```bash
  1578  ./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from components -q
  1579  ```
  1580  
  1581  ```json
  1582  [
  1583    {
  1584      "bom-ref": "pkg:npm/sample@2.0.0",
  1585      "description": "Node.js Sampler package",
  1586      "licenses": [
  1587        {
  1588          "license": {
  1589            "id": "MIT"
  1590          }
  1591        }
  1592      ],
  1593      "name": "sample",
  1594      "purl": "pkg:npm/sample@2.0.0",
  1595      "type": "library",
  1596      "version": "2.0.0"
  1597    },
  1598    {
  1599      "bom-ref": "pkg:npm/body-parser@1.19.0",
  1600      "description": "Node.js body parsing middleware",
  1601      "hashes": [
  1602        {
  1603          ...
  1604        }
  1605      ],
  1606      "licenses": [
  1607        {
  1608          "license": {
  1609            "id": "MIT"
  1610          }
  1611        }
  1612      ],
  1613      "name": "body-parser",
  1614      "purl": "pkg:npm/body-parser@1.19.0",
  1615      "type": "library",
  1616      "version": "1.19.0"
  1617    }
  1618  ]
  1619  ```
  1620  
  1621  **Note**: The command for this example only used the `--from` flag and did not need to supply `--select '*'` as this us the default.
  1622  
  1623  ##### Example: Filter result entries with a specified value
  1624  
  1625  In this example, the `--where` filter will be applied to a set of `properties` results to only include entries that match the specified regex.
  1626  
  1627  ```bash
  1628  ./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from metadata.properties --where name=urn:example.com:classification -q
  1629  ```
  1630  
  1631  ```json
  1632  [
  1633    {
  1634      "name": "urn:example.com:classification",
  1635      "value": "This SBOM is Confidential Information. Do not distribute."
  1636    }
  1637  ]
  1638  ```
  1639  
  1640  additionally, you can apply a `--select` clause to simply obtain the matching entry's `value`:
  1641  
  1642  ```bash
  1643  ./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --select value --from metadata.properties --where name=urn:example.com:classification -q
  1644  ```
  1645  
  1646  ```json
  1647  [
  1648    {
  1649      "value": "This SBOM is Confidential Information. Do not distribute."
  1650    }
  1651  ]
  1652  ```
  1653  
  1654  ---
  1655  
  1656  ### Component
  1657  
  1658  Primarily, this command is used to extract, filter and list CycloneDX BOM component data using `component list`.
  1659  
  1660  #### Component list supported formats
  1661  
  1662  This command supports the `--format` flag with any of the following values:
  1663  
  1664  - `txt` (default), `csv`, `md`
  1665  
  1666  #### Component list flags
  1667  
  1668  ##### Component list `--summary` flag
  1669  
  1670  Use the `--summary` flag on the `component list` command to produce a summary report with reduced column information.
  1671  
  1672  #### Component list examples
  1673  
  1674  ##### Example: `component list`
  1675  
  1676  This example shows the component list with all column information display. Since CycloneDX component data can be very extensive, many columns simply indicate the component `has` more data available which can be extracted using the `query` command if needed.
  1677  
  1678  ```bash
  1679  ./sbom-utility component list -i test/cyclonedx/1.6/specification/valid-bom-1.6.json -q
  1680  ```
  1681  
  1682  ```text
  1683  bom-ref                       group        type         name              version  description  copyright  supplier-name  supplier-url         manufacturer-name  manufacturer-url     publisher  purl                          swid-tag-id                                         cpe     mime-type  scope     number-hashes  number-licenses  has-pedigree  has-evidence  has-components  has-release-notes  has-model-card  has-data  has-tags  has-signature
  1684  -------                       -----        ----         ----              -------  -----------  ---------  -------------  ------------         -----------------  ----------------     ---------  ----                          -----------                                         ---     ---------  -----     -------------  ---------------  ------------  ------------  --------------  -----------------  --------------  --------  --------  -------------
  1685                                             application  Acme Application  9.1.1                                                                                                                                                 swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1                               0              0                false         false         false           false              false           false     false     false
  1686  pkg:npm/acme/component@1.0.0  com.acme     library      tomcat-catalina   9.0.14                                                                                                                  pkg:npm/acme/component@1.0.0                                                                                   4              1                true          false         false           false              false           false     false     false
  1687                                org.example  library      mylibrary         1.0.0                            Example, Inc.  https://example.com  Example-2, Inc.    https://example.org                                                                                                                  required  0              0                true          false         false           false              false           false     false     false
  1688  ```
  1689  
  1690  ##### Example: `component list` summary only
  1691  
  1692  The same BOM component information as in the previous example; however, using the summary flag to reduce the number of columns data.
  1693  
  1694  ```bash
  1695  ./sbom-utility component list -i test/cyclonedx/1.6/specification/valid-bom-1.6.json --summary -q
  1696  ```
  1697  
  1698  ```text
  1699  bom-ref                       group        type         name              version  description  copyright  supplier-name  supplier-url         manufacturer-name  manufacturer-url     publisher  purl                          swid-tag-id                                         cpe     number-hashes  number-licenses
  1700  -------                       -----        ----         ----              -------  -----------  ---------  -------------  ------------         -----------------  ----------------     ---------  ----                          -----------                                         ---     -------------  ---------------
  1701                                             application  Acme Application  9.1.1                                                                                                                                                 swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1          0              0
  1702  pkg:npm/acme/component@1.0.0  com.acme     library      tomcat-catalina   9.0.14                                                                                                                  pkg:npm/acme/component@1.0.0                                                              4              1
  1703                                org.example  library      mylibrary         1.0.0                            Example, Inc.  https://example.com  Example-2, Inc.    https://example.org                                                                                                       0              0
  1704  ```
  1705  
  1706  ---
  1707  
  1708  ### License
  1709  
  1710  This command is used to aggregate and summarize software, hardware and data license information included in the SBOM. It also displays license usage policies for resources based upon concluded by SPDX license identifier, license family or logical license expressions as defined in he current policy file (i.e., `license.json`).
  1711  
  1712  The `license` command supports the following subcommands:
  1713  
  1714  - [list](#license-list-subcommand) - list or create a summarized report of licenses found in input SBOM.
  1715    - [list with --summary flag](#license-list---summary-flag) - As full license information can be very large, a summary view is often most useful.
  1716  - [policy](#license-policy-subcommand) - list user configured license policies by SPDX license ID, family name and other filters.
  1717  
  1718  ---
  1719  
  1720  ### License `list` subcommand
  1721  
  1722  The `list` subcommand produces JSON output which contains an array of CycloneDX `LicenseChoice` data objects found in the BOM input file without component association.  `LicenseChoice` data, in general, may provide license information using registered SPDX IDs, license expressions (of SPDX IDs) or license names (not necessarily registered by SPDX).  License data may also include base64-encoded license or legal text that was used to determine a license's SPDX ID or name.
  1723  
  1724  #### License list supported formats
  1725  
  1726  This command supports the `--format` flag with any of the following values:
  1727  
  1728  - `json` (default), `csv`, `md`
  1729    - using the `--summary` flag: `txt` (default), `csv`, `md`
  1730  
  1731  #### License list result sorting
  1732  
  1733  - Results are not sorted for base `license list` subcommand.
  1734    - using the  `--summary` flag: results are sorted (ascending) by license key which can be one of license `id` (SPDX ID), `name` or `expression`.
  1735  
  1736  #### License list flags
  1737  
  1738  ##### License list `--summary` flag
  1739  
  1740  Use the `--summary` flag on the `license list` command to produce a summary report in `txt` (default) format as well as policy determination based upon the `license.json` declarations.
  1741  
  1742  #### License list examples
  1743  
  1744  ##### Example: license list JSON
  1745  
  1746  This example shows a few entries of the JSON output that exhibit the three types of license data described above:
  1747  
  1748  ```bash
  1749  ./sbom-utility license list -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --format json -q
  1750  ```
  1751  
  1752  ```json
  1753  [
  1754      {
  1755          "license": {
  1756              "$comment": "by license `id",
  1757              "id": "MIT",
  1758              "name": "",
  1759              "url": ""
  1760          }
  1761      },
  1762      {
  1763          "license": {
  1764              "$comment": "by license `expression",
  1765              "id": "",
  1766              "name": "",
  1767              "url": ""
  1768          },
  1769          "expression": "Apache-2.0 AND (MIT OR GPL-2.0-only)"
  1770      },
  1771      {
  1772          "license": {
  1773              "$comment": "by license `name` with full license encoding",
  1774              "id": "",
  1775              "name": "Apache 2",
  1776              "text": {
  1777                  "contentType": "text/plain",
  1778                  "encoding": "base64",
  1779                  "content": "CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFwYWNoZSBMaWNlbnNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFZlcnNpb24 ..."
  1780              },
  1781              "url": "https://www.apache.org/licenses/LICENSE-2.0.txt"
  1782          }
  1783      },
  1784      ...
  1785  ]
  1786  ```
  1787  
  1788  ###### Example: license list `--summary`
  1789  
  1790  This example shows the default text output from using the summary flag:
  1791  
  1792  ```bash
  1793  ./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary -q
  1794  ```
  1795  
  1796  ```bash
  1797  usage-policy  license-type  license                               resource-name      bom-ref                             bom-location
  1798  ------------  ------------  -------                               -------------      -------                             ------------
  1799  needs-review  id            ADSL                                  Foo                service:example.com/myservices/foo  services
  1800  needs-review  name          AGPL                                  Library J          pkg:lib/libraryJ@1.0.0              components
  1801  allow         name          Apache                                Library B          pkg:lib/libraryB@1.0.0              components
  1802  allow         id            Apache-1.0                            Library E          pkg:lib/libraryE@1.0.0              components
  1803  allow         id            Apache-2.0                            N/A                N/A                                 metadata.licenses
  1804  allow         id            Apache-2.0                            Library A          pkg:lib/libraryA@1.0.0              components
  1805  allow         id            Apache-2.0                            Library F          pkg:lib/libraryF@1.0.0              components
  1806  allow         expression    Apache-2.0 AND (MIT OR BSD-2-Clause)  Library B          pkg:lib/libraryB@1.0.0              components
  1807  allow         name          BSD                                   Library J          pkg:lib/libraryJ@1.0.0              components
  1808  deny          name          CC-BY-NC                              Library G          pkg:lib/libraryG@1.0.0              components
  1809  needs-review  name          GPL                                   Library H          pkg:lib/libraryH@1.0.0              components
  1810  needs-review  id            GPL-2.0-only                          Library C          pkg:lib/libraryC@1.0.0              components
  1811  needs-review  id            GPL-3.0-only                          Library D          pkg:lib/libraryD@1.0.0              components
  1812  allow         id            MIT                                   ACME Application   pkg:app/sample@1.0.0                metadata.component
  1813  allow         id            MIT                                   Library A          pkg:lib/libraryA@1.0.0              components
  1814  UNDEFINED     invalid       NOASSERTION                           Library NoLicense  pkg:lib/libraryNoLicense@1.0.0      components
  1815  UNDEFINED     invalid       NOASSERTION                           Bar                service:example.com/myservices/bar  services
  1816  needs-review  name          UFL                                   ACME Application   pkg:app/sample@1.0.0                metadata.component
  1817  ```
  1818  
  1819  - **Notes**
  1820    - **Usage policy** column values are derived from the `license.json` policy configuration file.
  1821      - A `usage policy` value of `UNDEFINED` indicates that `license.json` provided no entry that matched the declared license (`id` or `name`) in the SBOM.
  1822    - **License expressions** (e.g., `(MIT or GPL-2.0)`) with one term resolving to `UNDEFINED` and the the other term having a concrete policy will resolve to the "optimistic" policy for `OR` expressions and the "pessimistic" policy for `AND` expressions.  In addition, a warning of this resolution is emitted.
  1823  
  1824  ###### Example: license list summary with `--where` filter
  1825  
  1826  The list command results can be filtered using the `--where` flag using the column names in the report. These include `usage-policy`, `license-type`, `license`, `resource-name`, `bom-ref` and `bom-location`.
  1827  
  1828  The following example shows filtering of component licenses using the `license-type` column where the license was described as a `name` value:
  1829  
  1830  ```bash
  1831  ./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where license-type=name -q
  1832  ```
  1833  
  1834  ```bash
  1835  usage-policy  license-type  license   resource-name     bom-ref                 bom-location
  1836  ------------  ------------  -------   -------------     -------                 ------------
  1837  needs-review  name          AGPL      Library J         pkg:lib/libraryJ@1.0.0  components
  1838  allow         name          Apache    Library B         pkg:lib/libraryB@1.0.0  components
  1839  allow         name          BSD       Library J         pkg:lib/libraryJ@1.0.0  components
  1840  deny          name          CC-BY-NC  Library G         pkg:lib/libraryG@1.0.0  components
  1841  needs-review  name          GPL       Library H         pkg:lib/libraryH@1.0.0  components
  1842  needs-review  name          UFL       ACME Application  pkg:app/sample@1.0.0    metadata.component
  1843  ```
  1844  
  1845  In another example, the list is filtered by the `usage-policy` where the value is `needs-review`:
  1846  
  1847  ```bash
  1848  ./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where usage-policy=needs-review -q
  1849  ```
  1850  
  1851  ```bash
  1852  usage-policy  license-type  license       resource-name     bom-ref                             bom-location
  1853  ------------  ------------  -------       -------------     -------                             ------------
  1854  needs-review  id            ADSL          Foo               service:example.com/myservices/foo  services
  1855  needs-review  name          AGPL          Library J         pkg:lib/libraryJ@1.0.0              components
  1856  needs-review  name          GPL           Library H         pkg:lib/libraryH@1.0.0              components
  1857  needs-review  id            GPL-2.0-only  Library C         pkg:lib/libraryC@1.0.0              components
  1858  needs-review  id            GPL-3.0-only  Library D         pkg:lib/libraryD@1.0.0              components
  1859  needs-review  name          UFL           ACME Application  pkg:app/sample@1.0.0                metadata.component
  1860  ```
  1861  
  1862  ---
  1863  
  1864  ### License `policy` subcommand
  1865  
  1866  To view a report listing the contents of the current policy file (i.e., [`license.json`](https://github.com/CycloneDX/sbom-utility/blob/main/license.json)) which contains an encoding of known software and data licenses by SPDX ID and license family along with a configurable usage policy (i.e., `"allow"`, `"deny"` or `"needs-review"`).
  1867  
  1868  #### License policy supported formats
  1869  
  1870  This command supports the `--format` flag with any of the following values:
  1871  
  1872  - `txt` (default), `csv`, `md`
  1873  
  1874  #### License policy result sorting
  1875  
  1876  - Results are sorted by license policy `family`.
  1877  
  1878  #### License policy flags
  1879  
  1880  ##### list `--summary` flag
  1881  
  1882  Use the `--summary` flag on the `license policy list` command to produce a summary report with a reduced set of column data (i.e., it includes only the following columns:  `usage-policy`, `family`, `id`, `name`, `oci` (approved) `fsf` (approved), `deprecated`, and SPDX `reference` URL).
  1883  
  1884  ##### list `--wrap` flag
  1885  
  1886  Use the `--wrap` flag to toggle the wrapping of text within columns of the license policy report (`txt` format only) output using the values `true` or `false`. The default value is `false`.
  1887  
  1888  #### License policy examples
  1889  
  1890  ##### Example: license policy
  1891  
  1892  ```bash
  1893  ./sbom-utility license policy -q
  1894  ```
  1895  
  1896  ```bash
  1897  usage-policy  family    id            name                                osi    fsf    deprecated  reference                                    aliases                      annotations                  notes
  1898  ------------  ------    --            ----                                ---    ---    ----------  ---------                                    -------                      -----------                  -----
  1899  allow         0BSD      0BSD          BSD Zero Clause License             true   false  false       https://spdx.org/licenses/0BSD.html          Free Public License 1.0.0    APPROVED                     none
  1900  needs-review  ADSL      ADSL          Amazon Digital Services License     false  false  false       https://spdx.org/licenses/ADSL.html          none                         NEEDS-APPROVAL               none
  1901  allow         AFL       AFL-3.0       Academic Free License v3.0          true   true   false       https://spdx.org/licenses/AFL-3.0.html       none                         APPROVED                     none
  1902  needs-review  AGPL      AGPL-1.0      Affero General Public License v1.0  false  false  true        https://spdx.org/licenses/AGPL-1.0.html      none                         NEEDS-APPROVAL,AGPL-WARNING  none
  1903  allow         Adobe     Adobe-2006    Adobe Systems Incorporated CLA      false  false  false       https://spdx.org/licenses/Adobe-2006.html    none                         APPROVED                     none
  1904  allow         Apache    Apache-2.0    Apache License 2.0                  true   true   false       https://spdx.org/licenses/Apache-2.0.html    Apache License, Version 2.0  APPROVED                     none
  1905  allow         Artistic  Artistic-1.0  Artistic License 1.0                true   false  false       https://spdx.org/licenses/Artistic-1.0.html  none                         APPROVED                     none
  1906  ...
  1907  ```
  1908  
  1909  ###### Example: policy with `--summary` flag
  1910  
  1911  We can also apply the `--summary` flag to get a reduced set of columns that includes only the `usage-policy` along with the essential SPDX license information (e.g., no annotations or notes).
  1912  
  1913  ```bash
  1914  ./sbom-utility license policy --summary -q
  1915  ```
  1916  
  1917  ```bash
  1918  usage-policy  family    id            name                                osi     fsf     deprecated  reference
  1919  ------------  ------    --            ----                                ---     ---     ----------  ---------
  1920  allow         0BSD      0BSD          BSD Zero Clause License             true    false   false       https://spdx.org/licenses/0BSD.html
  1921  needs-review  ADSL      ADSL          Amazon Digital Services License     false   false   false       https://spdx.org/licenses/ADSL.html
  1922  allow         AFL       AFL-3.0       Academic Free License v3.0          true    true    false       https://spdx.org/licenses/AFL-3.0.html
  1923  needs-review  AGPL      AGPL-1.0      Affero General Public License v1.0  false   false   true        https://spdx.org/licenses/AGPL-1.0.html
  1924  allow         Adobe     Adobe-2006    Adobe Systems Incorporated CLA      false   false   false       https://spdx.org/licenses/Adobe-2006.html
  1925  allow         Apache    Apache-2.0    Apache License 2.0                  true    true    false       https://spdx.org/licenses/Apache-2.0.html
  1926  allow         Artistic  Artistic-1.0  Artistic License 1.0                true    true    false       https://spdx.org/licenses/Artistic-2.0.html
  1927  ...
  1928  ```
  1929  
  1930  ###### Example: policy with `--where` filter
  1931  
  1932  The following example shows filtering of  license policies using the `id` column:
  1933  
  1934  ```bash
  1935  ./sbom-utility license policy --where id=Apache -q
  1936  ```
  1937  
  1938  ```bash
  1939  usage-policy  family  id          name                osi     fsf     deprecated  reference                                  aliases         annotations  notes
  1940  ------------  ------  --          ----                ---     ---     ----------  ---------                                  -------         -----------  -----
  1941  allow         Apache  Apache-1.0  Apache v1.0         false   true    false       https://spdx.org/licenses/Apache-1.0.html  none            APPROVED     none
  1942  allow         Apache  Apache-1.1  Apache v1.1         true    true    false       https://spdx.org/licenses/Apache-1.1.html  none            APPROVED     Superseded by Apache-2.0
  1943  allow         Apache  Apache-2.0  Apache License 2.0  true    true    false       https://spdx.org/licenses/Apache-2.0.html  Apache License  APPROVED     none
  1944  
  1945  ```
  1946  
  1947  ###### Example: policy with `--wrap` flag
  1948  
  1949  ```bash
  1950  ./sbom-utility license policy --wrap=true -q
  1951  ```
  1952  
  1953  ```bash
  1954  usage-policy  family    id             name                          osi     fsf     deprecated  reference                                     aliases                           annotations             notes
  1955  ------------  ------    --             ----                          ---     ---     ----------  ---------                                     -------                           -----------             -----
  1956  allow         0BSD      0BSD           BSD Zero Clause Lice (20/23)  true    false   false       https://spdx.org/licenses/0BSD.html           Free Public License 1.0. (24/25)  APPROVED                none
  1957  needs-review  ADSL      ADSL           Amazon Digital Servi (20/31)  false   false   false       https://spdx.org/licenses/ADSL.html                                             NEEDS-APPROVAL          none
  1958  allow         AFL       AFL-3.0        Academic Free Licens (20/26)  true    true    false       https://spdx.org/licenses/AFL-3.0.ht (36/38)                                    APPROVED                none
  1959  needs-review  AGPL      AGPL-1.0       Affero General Publi (20/34)  false   false   true        https://spdx.org/licenses/AGPL-1.0.h (36/39)                                    NEEDS-APPROVAL          none
  1960                                                                                                                                                                                   AGPL-WARNING
  1961  needs-review  APSL      APSL-2.0       Apple Public Source  (20/31)  true    true    false       https://spdx.org/licenses/APSL-2.0.h (36/39)                                    NEEDS-APPROVAL          none
  1962  allow         Adobe     Adobe-2006     Adobe Systems Incorp (20/56)  false   false   false       https://spdx.org/licenses/Adobe-2006 (36/41)                                    APPROVED                none
  1963  allow         Apache    Apache-2.0     Apache License 2.0            true    true    false       https://spdx.org/licenses/Apache-2.0 (36/41)  Apache License, Version  (24/27)  APPROVED                none
  1964  allow         Artistic  Artistic-2.0   Artistic License 2.0          true    true    false       https://spdx.org/licenses/Artistic-2 (36/43)                                    APPROVED                none
  1965  ...
  1966  ```
  1967  
  1968  #### License policy notes
  1969  
  1970  - Currently, the default `license.json` file, used to derive the `usage-policy` data, does not contain entries for the entire set of SPDX 3.2 license templates.
  1971    - An issue [12](https://github.com/CycloneDX/sbom-utility/issues/12) is open to add parity.
  1972  - Annotations (tags) and notes can be defined within the `license.json` file and one or more assigned each license entry.
  1973  <!-- - Column data is, by default, truncated in `txt` format views only. In these cases, the number of characters shown out of the total available will be displayed at the point of truncation (e.g., seeing `(24/26)` in a column would indicate 24 out of 26 characters were displayed). -->
  1974  - For backwards compatibility, the `--where` filter supports the key `spdx-id` as an alias for `id`.
  1975  
  1976  ---
  1977  
  1978  ### Resource
  1979  
  1980  The `resource` command is geared toward inspecting various resources types and their information from SBOMs against future maturity models being developed as part of the [OWASP Software Component Verification Standard (SCVS)](https://owasp.org/www-project-software-component-verification-standard/).  In the SCVS model, a "resource" is the parent classification for software (components), services, Machine Learning (ML) models, data, hardware, tools and more.
  1981  
  1982  Primarily, the command is used to generate lists of resources, by type, that are included in a CycloneDX SBOM by invoking `resource list`.
  1983  
  1984  #### Resource supported output formats
  1985  
  1986  This command supports the `--format` flag with any of the following values:
  1987  
  1988  - `txt` (default), `csv`, `md`
  1989  
  1990  #### Resource result sorting
  1991  
  1992  Currently, all `resource list` command results are sorted by resource `type` then by resource `name` (required field).
  1993  
  1994  #### Resource Examples
  1995  
  1996  #### Example: resource list
  1997  
  1998  ```bash
  1999  ./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json -q
  2000  ```
  2001  
  2002  ```bash
  2003  resource-type  group   name               version  description                       bom-ref
  2004  -------------  -----   ----               -------  -----------                       -------
  2005  component              ACME Application   2.0.0    ACME sample application           pkg:app/sample@1.0.0
  2006  component              Library A          1.0.0    Library A description             pkg:lib/libraryA@1.0.0
  2007  component              Library C          1.0.0    Library C description.            pkg:lib/libraryC@1.0.0
  2008  component              Library F          1.0.0    Library F description.            pkg:lib/libraryF@1.0.0
  2009  component              Library G          1.0.0    Library G description.            pkg:lib/libraryG@1.0.0
  2010  component              Library H          1.0.0    Library H description.            pkg:lib/libraryH@1.0.0
  2011  component              Library NoLicense  1.0.0    Library "NoLicense" description.  pkg:lib/libraryNoLicense@1.0.0
  2012  component      blue    Library B          1.0.0    Library B description.            pkg:lib/libraryB@1.0.0
  2013  component      blue    Library E          1.0.0    Library E description.            pkg:lib/libraryE@1.0.0
  2014  component      green   Library D          1.0.0    Library D description.            pkg:lib/libraryD@1.0.0
  2015  component      green   Library J          1.0.0    Library J description.            pkg:lib/libraryJ@1.0.0
  2016  service                Bar                         Bar service                       service:example.com/myservices/bar
  2017  service                Foo                         Foo service                       service:example.com/myservices/foo
  2018  
  2019  ```
  2020  
  2021  ##### Example: resource list using `--type service`
  2022  
  2023  This example uses the `type` flag to specific `service`.  The other valid type is `component`.  Future versions of CycloneDX schema will include more resource types such as "ml" (machine learning) or "tool".
  2024  
  2025  ```bash
  2026  ./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --type service -q
  2027  ```
  2028  
  2029  ```bash
  2030  resource-type  group   name    version  description  bom-ref
  2031  -------------  -----   ----    -------  -----------  -------
  2032  service                Bar              Bar service  service:example.com/myservices/bar
  2033  service                Foo              Foo service  service:example.com/myservices/foo
  2034  ```
  2035  
  2036  **Note** The results would be equivalent to using the `--where` filter:
  2037  
  2038  ```bash
  2039  ./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "resource-type=service" -q
  2040  ```
  2041  
  2042  ##### Example: list with `name` regex match
  2043  
  2044  This example uses the `where` filter on the `name` field. In this case we supply an exact "startswith" regex. for the `name` filter.
  2045  
  2046  ```bash
  2047  ./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "name=Library A" -q
  2048  ```
  2049  
  2050  ```bash
  2051  resource-type  group   name       version  description            bom-ref
  2052  -------------  -----   ----       -------  -----------            -------
  2053  component              Library A  1.0.0    Library A description  pkg:lib/libraryA@1.0.0
  2054  ```
  2055  
  2056  ---
  2057  
  2058  ### Schema
  2059  
  2060  You can verify which formats, schemas, versions and variants are available for validation by using the `schema` command.
  2061  
  2062  - **Note**: The `schema` command will default to the `list` subcommand if omitted.
  2063  
  2064  #### Schema supported output formats
  2065  
  2066  This command supports the `--format` flag with any of the following values:
  2067  
  2068  - `txt` (default), `csv`, `md`
  2069  
  2070  #### Schema result sorting
  2071  
  2072  - Formatted results are sorted by `format` (ascending), `version` (descending) and `schema` (descending)
  2073  
  2074  #### Schema examples
  2075  
  2076  ##### Example: schema list
  2077  
  2078  ```bash
  2079  ./sbom-utility schema list -q
  2080  ```
  2081  
  2082  ```bash
  2083  name            variant      format     version   file                                             url
  2084  ----            -------      ------     -------   ----                                             ---
  2085  CycloneDX v1.6  development  CycloneDX  1.6       schema/cyclonedx/1.6/bom-1.6.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/1.6-dev/schema/bom-1.6.schema.json
  2086  CycloneDX v1.5  (latest)     CycloneDX  1.5       schema/cyclonedx/1.5/bom-1.5.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.5.schema.json
  2087  CycloneDX v1.4  (latest)     CycloneDX  1.4       schema/cyclonedx/1.4/bom-1.4.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.4.schema.json
  2088  CycloneDX v1.4  custom       CycloneDX  1.4       schema/test/bom-1.4-custom.schema.json
  2089  CycloneDX v1.3  (latest)     CycloneDX  1.3       schema/cyclonedx/1.3/bom-1.3.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3.schema.json
  2090  CycloneDX v1.3  custom       CycloneDX  1.3       schema/test/bom-1.3-custom.schema.json
  2091  CycloneDX v1.3  strict       CycloneDX  1.3       schema/cyclonedx/1.3/bom-1.3-strict.schema.json  https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3-strict.schema.json
  2092  CycloneDX v1.2  (latest)     CycloneDX  1.2       schema/cyclonedx/1.2/bom-1.2.schema.json         https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2.schema.json
  2093  CycloneDX v1.2  strict       CycloneDX  1.2       schema/cyclonedx/1.2/bom-1.2-strict.schema.json  https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2-strict.schema.json
  2094  SPDX v2.3       (latest)     SPDX       SPDX-2.3  schema/spdx/2.3/spdx-schema.json                 https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json
  2095  SPDX v2.3.1     development  SPDX       SPDX-2.3  schema/spdx/2.3.1/spdx-schema.json               https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3.1/schemas/spdx-schema.json
  2096  SPDX v2.2.2     (latest)     SPDX       SPDX-2.2  schema/spdx/2.2.2/spdx-schema.json               https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.2/schemas/spdx-schema.json
  2097  SPDX v2.2.1     2.2.1        SPDX       SPDX-2.2  schema/spdx/2.2.1/spdx-schema.json               https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json
  2098  ```
  2099  
  2100  #### Adding schemas
  2101  
  2102  Entries for new or "custom" schemas can be added to the `config.json` file by adding a new schema entry and then will need to pass that file on the command line using the `--config-schema` flag.
  2103  
  2104  These new schema entries will tell the schema loader where to find the JSON schema file locally, relative to the utility's executable.
  2105  
  2106  For details see the "[Adding new SBOM formats, schema versions and variants](#adding-new-sbom-formats-schema-versions-and-variants)" section.
  2107  
  2108  #### Embedding schemas
  2109  
  2110  If you wish to have the new schema *embedded in the executable*, simply add it to the project's `resources` subdirectory following the format and version-based directory structure.
  2111  
  2112  ---
  2113  
  2114  ### Vulnerability
  2115  
  2116  This command will extract basic vulnerability report data from an SBOM that has a "vulnerabilities" list or from a standalone VEX in CycloneDX format. It includes the ability to filter reports data by applying regex to any of the named column data.
  2117  
  2118  #### Vulnerability supported output formats
  2119  
  2120  Use the `--format` flag on the to choose one of the supported output formats:
  2121  
  2122  - txt (default), csv, md
  2123  
  2124  #### Vulnerability result sorting
  2125  
  2126  - `txt`, `csv` and `md` formatted results are sorted by vulnerability `id` (descending) then by `created` date (descending).
  2127  - `json` results are not sorted
  2128  
  2129  #### Vulnerability Examples
  2130  
  2131  ##### Example: Vulnerability list
  2132  
  2133  The `list` subcommand provides a complete view of most top-level, vulnerability fields.
  2134  
  2135  ```bash
  2136  ./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json -q
  2137  ```
  2138  
  2139  ```bash
  2140  id              bom-ref  cwe-ids  cvss-severity                                                source-name  source-url                                       published   updated     created     rejected  analysis-state  analysis-justification  description
  2141  --              -------  -------  -------------                                                -----------  ----------                                       ---------   -------     -------     --------  --------------  ----------------------  -----------
  2142  CVE-2023-42004           502      CVSSv31: 7.5 (high)                                          NVD          https://nvd.nist.gov/vuln/detail/CVE-2023-42004  2023-10-02  2023-10-02  2023-10-02            UNDEFINED       UNDEFINED               In FasterXML jackson-databind before 2.13.4, resource exhaustion can occur because of a lack of a check in BeanDeserializer._deserializeFromArray to prevent use of deeply nested arrays. An application is vulnerable only with certain customized choices for deserialization.
  2143  CVE-2023-42003           502      CVSSv31: 7.5 (high)                                          NVD          https://nvd.nist.gov/vuln/detail/CVE-2023-42003  2023-10-02  2023-10-02  2023-10-02            UNDEFINED       UNDEFINED               In FasterXML jackson-databind before 2.14.0-rc1, resource exhaustion can occur because of a lack of a check in primitive value deserializers to avoid deep wrapper array nesting, when the UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled. Additional fix version in 2.13.4.1 and 2.12.17.1
  2144  CVE-2020-25649           611      CVSSv31: 7.5 (high), CVSSv31: 8.2 (high), CVSSv31: 0 (none)  NVD          https://nvd.nist.gov/vuln/detail/CVE-2020-25649  2020-12-03  2023-02-02  2020-12-03            not_affected    code_not_reachable      com.fasterxml.jackson.core:jackson-databind is a library which contains the general-purpose data-binding functionality and tree-model for Jackson Data Processor.  Affected versions of this package are vulnerable to XML External Entity (XXE) Injection. A flaw was found in FasterXML Jackson Databind, where it does not have entity expansion secured properly in the DOMDeserializer class. The highest threat from this vulnerability is data integrity.
  2145  ```
  2146  
  2147  ###### Example: Vulnerability list summary
  2148  
  2149  This example shows the default text output from using the `--summary` flag:
  2150  
  2151  ```bash
  2152  ./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --summary -q
  2153  ```
  2154  
  2155  ```bash
  2156  id              cvss-severity        source-name  published   description
  2157  --              -------------        -----------  ---------   -----------
  2158  CVE-2023-42004  CVSSv31: 7.5 (high)  NVD          2023-10-02  In FasterXML jackson-databind before 2.13.4, resource exhaustion can occur because of a lack of a check in BeanDeserializer._deserializeFromArray to prevent use of deeply nested arrays. An application is vulnerable only with certain customized choices for deserialization.
  2159  CVE-2023-42003  CVSSv31: 7.5 (high)  NVD          2023-10-02  In FasterXML jackson-databind before 2.14.0-rc1, resource exhaustion can occur because of a lack of a check in primitive value deserializers to avoid deep wrapper array nesting, when the UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled. Additional fix version in 2.13.4.1 and 2.12.17.1
  2160  CVE-2020-25649  CVSSv31: 7.5 (high)  NVD          2020-12-03  com.fasterxml.jackson.core:jackson-databind is a library which contains the general-purpose data-binding functionality and tree-model for Jackson Data Processor.  Affected versions of this package are vulnerable to XML External Entity (XXE) Injection. A flaw was found in FasterXML Jackson Databind, where it does not have entity expansion secured properly in the DOMDeserializer class. The highest threat from this vulnerability is data integrity.
  2161  ```
  2162  
  2163  ##### Example: Vulnerability list with `--where` filter with `description` key
  2164  
  2165  ```bash
  2166  ./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --where description=XXE -q
  2167  ```
  2168  
  2169  ```bash
  2170  id              bom-ref  cwe-ids  cvss-severity                                                source-name  source-url                                       published   updated     created     rejected  analysis-state  analysis-justification  description
  2171  --              -------  -------  -------------                                                -----------  ----------                                       ---------   -------     -------     --------  --------------  ----------------------  -----------
  2172  CVE-2020-25649           611      CVSSv31: 7.5 (high), CVSSv31: 8.2 (high), CVSSv31: 0 (none)  NVD          https://nvd.nist.gov/vuln/detail/CVE-2020-25649  2020-12-03  2023-02-02  2020-12-03            not_affected    code_not_reachable      com.fasterxml.jackson.core:jackson-databind is a library which contains the general-purpose data-binding functionality and tree-model for Jackson Data Processor.  Affected versions of this package are vulnerable to XML External Entity (XXE) Injection. A flaw was found in FasterXML Jackson Databind, where it does not have entity expansion secured properly in the DOMDeserializer class. The highest threat from this vulnerability is data integrity.
  2173  ```
  2174  
  2175  ##### Example: Vulnerability list with `--where` filter with `analysis-state` key
  2176  
  2177  ```bash
  2178  ./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --where analysis-state=not_affected -q
  2179  ```
  2180  
  2181  ```bash
  2182  id              bom-ref  cwe-ids  cvss-severity                                                source-name  source-url                                       published   updated     created     rejected  analysis-state  analysis-justification  description
  2183  --              -------  -------  -------------                                                -----------  ----------                                       ---------   -------     -------     --------  --------------  ----------------------  -----------
  2184  CVE-2020-25649           611      CVSSv31: 7.5 (high), CVSSv31: 8.2 (high), CVSSv31: 0 (none)  NVD          https://nvd.nist.gov/vuln/detail/CVE-2020-25649  2020-12-03  2023-02-02  2020-12-03            not_affected    code_not_reachable      com.fasterxml.jackson.core:jackson-databind is a library which contains the general-purpose data-binding functionality and tree-model for Jackson Data Processor.  Affected versions of this package are vulnerable to XML External Entity (XXE) Injection. A flaw was found in FasterXML Jackson Databind, where it does not have entity expansion secured properly in the DOMDeserializer class. The highest threat from this vulnerability is data integrity.
  2185  ```
  2186  
  2187  ---
  2188  
  2189  ### Completion
  2190  
  2191  This command will generate command-line completion scripts, for the this utility, customized for various supported shells.
  2192  
  2193  The completion command can be invoked as follows:
  2194  
  2195  ```bash
  2196  ./sbom_utility completion [shell]
  2197  ```
  2198  
  2199  where valid values for `shell` are:
  2200  
  2201  - bash
  2202  - fish
  2203  - powershell
  2204  - zsh
  2205  
  2206  ---
  2207  
  2208  ### Help
  2209  
  2210  The utility supports the `help` command for the root command as well as any supported commands
  2211  
  2212  For example, to list top-level (root command) help which lists the supported "Available Commands":
  2213  
  2214  ```bash
  2215  ./sbom-utility help
  2216  ```
  2217  
  2218  A specific command-level help listing is also available. For example, you can access the help for the `validate` command:
  2219  
  2220  ```bash
  2221  ./sbom-utility help validate
  2222  ```
  2223  
  2224  ---
  2225  
  2226  ## Experimental Commands
  2227  
  2228  This section contains *experimental* commands that will be promoted once vetted by the community over two or more point releases.
  2229  
  2230  ### Diff
  2231  
  2232  This *experimental* command will compare two *similar* BOMs and return the delta (or "diff") in JSON (diff-patch format) or text. This functionality is "JSON aware" and based upon code ancestral to that used to report file diffs between `git commit`s.
  2233  
  2234  ##### Recommendations
  2235  
  2236  - *Even with BOMs that **SHOULD** be similar, it is recommended to use the **[trim](#trim)** command to remove data that changes within a BOM from one generation to another *or* is often proprietary such as: **bom-ref**, **hashes**, **timestamp**(s), **properties**, etc.*.
  2237  - *In addition, it is recommended that you also `--normalize` trimmed output data to better guarantee ordering of fields and array data.*
  2238  
  2239  ##### Notes
  2240  
  2241  - This command is undergoing analysis and tests which are exposing some underlying issues around "moved" objects in dependent diff-patch packages that may not be fixable and have no alternatives.
  2242    - *Specifically, the means by which "moved" objects are assigned "similarity" scores appears flawed in the case of JSON.*
  2243    - *Additionally, some of the underlying code relies upon Go maps which do not preserve key ordering.*
  2244  
  2245  #### Diff supported output formats
  2246  
  2247  Use the `--format` flag on the to choose one of the supported output formats:
  2248  
  2249  - txt (default), json
  2250  
  2251  #### Diff Examples
  2252  
  2253  ##### Example: Add, delete and modify
  2254  
  2255  ```bash
  2256  ./sbom-utility diff -i test/diff/json-array-order-change-with-add-and-delete-base.json -r test/diff/json-array-order-change-with-add-and-delete-delta.json --format txt --colorize=true -q
  2257  ```
  2258  
  2259  ```bash
  2260   {
  2261     "licenses": [
  2262       0: {
  2263         "license": {
  2264  -        "id": "Apache-1.0"
  2265  +        "id": "GPL-2.0"
  2266         }
  2267       },
  2268  -+    2=>1: {
  2269  -+      "license": {
  2270  -+        "id": "GPL-3.0-only"
  2271  -+      }
  2272  -+    },
  2273       2: {
  2274         "license": {
  2275           "id": "GPL-3.0-only"
  2276         }
  2277       },
  2278       3: {
  2279         "license": {
  2280           "id": "MIT"
  2281         }
  2282       }
  2283     ]
  2284   }
  2285  ```
  2286  
  2287  ---
  2288  
  2289  ## Contributing
  2290  
  2291  Contributions are welcome under the Apache 2.0 license.  Help is wanted in the following areas:
  2292  
  2293  - [TODO list](#todo-list)
  2294  - [Priority features](#priority-features)
  2295  
  2296  #### TODO list
  2297  
  2298  The entirety of the code contains the tag "**TODO**" with comments of things that are features or improvements conceived while authoring the base functionality.  Most of these do not have active issues opened form them.
  2299  
  2300  Feel free to "grep" for the "TODO" tag, open an issue and/or submit a draft PR.
  2301  
  2302  #### Priority features
  2303  
  2304  An ad-hoc list of featured "TODOs" geared at making the tool more accessible, extensible and useful especially around "core" commands such as validation.
  2305  
  2306  - **Merge command** Support merge of two (both validated) SBOMs with de-duplication and configurable. Please note that some method of normalization prior to merge will be necessary.
  2307  - **Remote Schema loading** Support using SBOM schema files that are remotely hosted  (network accessible) from known, trusted source locations (e.g., releases of SPDX, CycloneDX specification schemas). Note that the config file has an existing `url` field per entry that can be used for this purpose.
  2308  - **--orderby** Support ordering of query result sets by comparison of values from a specified field key.
  2309  - **license.json** Document license policy configuration JSON schema structure and how to add entries relative to a CycloneDX `LicenseChoice` object for entries with SPDX IDs and those without.
  2310  - **license.json** Add entries for all SPDX licenses listed in v3.21.
  2311    - See issue: https://github.com/CycloneDX/sbom-utility/issues/12
  2312  - **Go libraries** Replace `go-prettyjson`, `go-multimap` libraries with alternatives that produce maintained releases.
  2313  
  2314  ---
  2315  
  2316  ## Design considerations
  2317  
  2318  ### Memory safety
  2319  
  2320  The utility itself is written in `Go` to advantage the language's built-in typing enforcement and memory safe features and its ability to be compiled for a wide range of target platforms and architectures.
  2321  
  2322  ### Consistent output
  2323  
  2324  The utility also is designed to produce output formats (e.g., JSON) and handle exit codes consistently to make it immediately useful standalone or as part of automated Continuous Integration (CI) tool chains for downstream use or inspection.
  2325  
  2326  ### Security and integrity focus
  2327  
  2328  Further commands and reports are planned that prioritize use cases that enable greater insight and analysis of the legal, security and compliance data captured in the SBOM such as component **provenance** and **signage** (e.g., verifying resource identities by hashes or fingerprints).
  2329  
  2330  In addition, inclusion of **Continuous Integration and Delivery (CI/CD)** or "build integrity" information around the BOM component is anticipated as part of the CycloneDX Formulation work which will require features for workflow insights.
  2331  
  2332  ### Functional priorities
  2333  
  2334  The utility additionally prioritizes commands that help provide insight into contents of the BOM to search for and report on missing (i.e., completeness) or specific data requirements (e.g., organization or customer-specific requirements).
  2335  
  2336  In general, the goal of these prioritized commands is to support data verification for many of the primary BOM use cases as identified by the CycloneDX community (see https://cyclonedx.org/use-cases/).  Functional development has focused on those use cases that verify inventory (resource identity), legal compliance (e.g., license), and security analysis (e.g., vulnerability) which are foundational to any SBOM.
  2337  
  2338  ### Support all BOM formats
  2339  
  2340  In the future, we envision support for additional kinds of BOMs (e.g., Hardware (HBOM), Machine Learning (MLBOM), etc.) with each again having different data requirements and levels of maturity which will increase the need for domain-specific validation.  Specifically, this utility intends to support the work of the [OWASP Software Component Verification Standard (SCVS)](https://owasp.org/www-project-software-component-verification-standard/) which is defining a BOM Maturity Model (BMM).
  2341  
  2342  ---
  2343  
  2344  ## Development
  2345  
  2346  The following development-oriented topics are included in this section:
  2347  
  2348  - [Prerequisites](#prerequisites)
  2349  - [Building](#building)
  2350  - [Running from source](#running-from-source)
  2351  - [Debugging](#debugging)
  2352    - [Using VSCode](#vscode)
  2353  - [Adding new SBOM formats, schema versions and variants](#adding-new-sbom-formats-schema-versions-and-variants)
  2354  
  2355  ### Prerequisites
  2356  
  2357  - Go v1.20.1 or higher: see [https://go.dev/doc/install](https://go.dev/doc/install)
  2358  - `git` client: see [https://git-scm.com/downloads](https://git-scm.com/downloads)
  2359  
  2360  ### Building
  2361  
  2362  To build an executable of the utility compatible with your local computer's architecture use the `build` target in the project's `Makefile`:
  2363  
  2364  ```bash
  2365  cd sbom-utility/
  2366  make build
  2367  ```
  2368  
  2369  The will produce a binary named `sbom-utility` with version set to `latest` in the project's `release` directory.
  2370  
  2371  ```bash
  2372  $ ls
  2373  -rwxr-xr-x   1 User1  staff  11501122 Jan 24 08:29 sbom-utility
  2374  ```
  2375  
  2376  ```bash
  2377  $ ./sbom-utility version
  2378  Welcome to the sbom-utility! Version `latest` (sbom-utility) (darwin/arm64)
  2379  ```
  2380  
  2381  **Note** The binary created using `make build` will be for the local system's operating system and architecture (i.e., `GOOS`, `GOARCH`).  This would effectively match what would be reported using the `uname -s -m` unix command when run on the same local system.
  2382  
  2383  If you wish to build binaries for all supported combinations of `GOOS` and `GOARCH` values, use the `release` target (i.e., `make release`) which will produce named binaries of the form `sbom-utility-${GOOS}-${GOARCH}` under the `release` directory (e.g., `sbom-utility-darwin-amd64`).
  2384  
  2385  ### Running from source
  2386  
  2387  Developers can run using the current source code in their local branch using `go run main.go`. For example:
  2388  
  2389  ```bash
  2390  go run main.go validate -i test/cyclonedx/cdx-1-4-mature-example-1.json
  2391  ```
  2392  
  2393  ### Debugging
  2394  
  2395  #### VSCode
  2396  
  2397  This project was developed using VSCode and can be seamlessly loaded as a project.
  2398  
  2399  ##### Debugging globals
  2400  
  2401  In order to see global variables while debugging a specific configuration, you can add the `"showGlobalVariables": true` to it within your `launch.json` config. file:
  2402  
  2403  ```json
  2404  {
  2405      "showGlobalVariables": true,
  2406      "name": "Test name",
  2407      "type": "go",
  2408      "request": "launch",
  2409      "mode": "debug",
  2410      "program": "main.go",
  2411      "args": ["validate", "-i", "test/cyclonedx/cdx-1-3-min-required.json","-t"]
  2412  },
  2413  ```
  2414  
  2415  or add it globally to the `settings.json` file:
  2416  
  2417  1. Use `Command-Shift-P` to open `settings.json`
  2418  2. Select "Preferences: Open Settings (JSON)"
  2419  3. Add the following block at the top level:
  2420  
  2421  ```json
  2422  "go.delveConfig": {
  2423      "showGlobalVariables": true
  2424  },
  2425  ```
  2426  
  2427  **Note**: *The `showGlobalVariables` setting was only recently disabled as the default in VSCode as a stop-gap measure due to performance (loading) problems under Windows.*
  2428  
  2429  ### Adding new SBOM formats, schema versions and variants
  2430  
  2431  The utility uses the [`config.json`](./config.json) file (either the default, embedded version or the equivalent provided on the command line using `--config-schema` flag) to lookup supported formats and their associated versioned JSON schema files.  To add another SBOM format simply add another entry to the `format` array in the document:
  2432  
  2433  ```json
  2434  {
  2435    "canonicalName": "SPDX",
  2436    "propertyKeyFormat": "SPDXID",
  2437    "propertyKeyVersion": "spdxVersion",
  2438    "propertyValueFormat": "SPDXRef-DOCUMENT",
  2439    "schemas": [
  2440        {
  2441            ...
  2442        }
  2443    ]
  2444     ...
  2445  }
  2446  ```
  2447  
  2448  The value for `propertyKeyFormat` should be the exact name of key field that would appear in the JSON SBOM itself which can be used to confirm it is indeed a format match.  In addition, the corresponding value to match for that key should be declared in the `propertyValueFormat` value.
  2449  
  2450  The fields `canonicalName`, `propertyKeyFormat`, `propertyKeyVersion`, and `propertyValueFormat` are required. The `format` object **MUST** have at least one valid `schema` object.
  2451  
  2452  An example `schema` object for the canonical SPDX v2.3 (default, no variant) schema appears as follows:
  2453  
  2454  ```json
  2455  {
  2456    {
  2457        "version": "SPDX-2.3",
  2458        "variant": "",
  2459        "name": "SPDX v2.3",
  2460        "file": "schema/spdx/2.3/spdx-schema.json",
  2461        "development": "https://github.com/spdx/spdx-spec/blob/development/v2.3/schemas/spdx-schema.json",
  2462        "url": "https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json",
  2463        "default": true
  2464    },
  2465  },
  2466  ```
  2467  
  2468  - Add a copy of the JSON schema file locally in the project under the structure `resources/schema/<format>/<version>/<schema filename>`.
  2469    - **Note** If the schema exists under the `resources` directory, it will automatically be embedded in in the executable binary when built using `go build` which includes using the project's `Makefile`.
  2470  - Assure **only one** `schema` object entry for a given format and version has the value `latest` set to `true`.  This latest schema will be used when the SBOM being validated does not have a clear version declared **or** used with the `--force latest` flag.
  2471  - If you have a customized or "variant" version of a schema (with the same format and version values) you wish to use for validation (e.g., a `corporate`or `staging` version with added requirements or for testing an unreleased version), you can create an entry that has the same `version` as another entry, but also declare its `variant` name *(non-empty value)*.  This value can be supplied on the commend line with the `--variant <variant name>` flag to force the validator to use it instead of the default *(empty variant value)*.
  2472  
  2473  ---
  2474  
  2475  ## Testing
  2476  
  2477  Testing implementation and invocation, with examples, is described in this section including:
  2478  
  2479  - [Authoring Go test files](#authoring-go-test-files)
  2480  - [Running tests](#running-tests)
  2481  
  2482  ### Authoring Go test files
  2483  
  2484  The built-in `go test` command will execute all functional tests that appear in files named with the pattern: `<filename>_test.go`. These files are executed from within the same directory (package) where its respective `<filename>.go` source code file is located and sets that same as the "working directory".
  2485  
  2486  *For example,* tests in the `validate_test.go` file are executed from the `cmd` subdirectory.
  2487  
  2488  This is normally a problem as the actual test SBOM JSON test files are located relative the project root, one level higher, and would not be found by the "working directory".  In order to correct for that, the test working directory is automatically changed for all tests within the `TestMain` routine found in `root_test.go`.
  2489  
  2490  ### Running tests
  2491  
  2492  The `Makefile` includes a `test` target for convenience which will use `go test` to run all tests found in all subdirectories:
  2493  
  2494  ```bash
  2495  make test
  2496  ```
  2497  
  2498  #### Running tests for a single package
  2499  
  2500  The `test_cmd` target will use run only the test found in the `cmd` package:
  2501  
  2502  ```bash
  2503  make test_cmd
  2504  ```
  2505  
  2506  The `test_schema` target will use run only the test found in the `schema` package:
  2507  
  2508  ```bash
  2509  make test_schema
  2510  ```
  2511  
  2512  #### Using `go test`
  2513  
  2514  Example: running all tests in the `cmd` package:
  2515  
  2516  ```bash
  2517  go test github.com/CycloneDX/sbom-utility/cmd -v
  2518  ```
  2519  
  2520  Example: running all tests in the `schema` package:
  2521  
  2522  ```bash
  2523  go test github.com/CycloneDX/sbom-utility/schema -v
  2524  ```
  2525  
  2526  #### Running tests in quiet mode
  2527  
  2528  Run in "quiet" mode to not see error test output:
  2529  
  2530  ```bash
  2531  go test github.com/CycloneDX/sbom-utility/cmd -v --quiet
  2532  ```
  2533  
  2534  run an individual test within the `cmd` package:
  2535  
  2536  ```bash
  2537  go test github.com/CycloneDX/sbom-utility/cmd -v -run TestValidateCdx14MinRequiredBasic
  2538  ```
  2539  
  2540  #### Debugging `go test`
  2541  
  2542  Simply append the flags `--args --trace` or `--args --debug` to your `go test` command to enable trace or debug output for your designated test(s):
  2543  
  2544  ```bash
  2545  go test github.com/CycloneDX/sbom-utility/cmd -v --args --trace
  2546  ```
  2547  
  2548  **Note**: You should always use the `--args` flag of `go test` as this will assure non-conflict with `go test` built-in flags which is the case with the `--trace` flag.
  2549  
  2550  #### Eliminating extraneous test output
  2551  
  2552  Several tests will still output error and warning messages as designed.  If these messages are distracting, you can turn them off using the `--quiet` flag.
  2553  
  2554  ```bash
  2555  go test github.com/CycloneDX/sbom-utility/cmd -v --quiet
  2556  ```
  2557  
  2558  ---
  2559  
  2560  ## Releasing
  2561  
  2562  ### GitHub
  2563  
  2564  In order to initiate the release workflow, simply go to the release page of the repository:
  2565  
  2566  - [https://github.com/CycloneDX/sbom-utility/releases](https://github.com/CycloneDX/sbom-utility/releases)
  2567  
  2568  and click on the `Draft a new release` button.  Follow the instructions to create a new version tag, provide an appropriate release title and description and `publish` the release.  The GitHub release workflow will be triggered automatically.
  2569  
  2570  ### Local
  2571  
  2572  For local development, you may choose to make a release on your machine using the `Makefile` directive `release`:
  2573  
  2574  ```bash
  2575  make release
  2576  ```
  2577  
  2578  After all builds are done, the binaries and config. files can be verified to be in the target `release` directory:
  2579  
  2580  ```bash
  2581  ls release
  2582  ```
  2583  
  2584  ```bash
  2585  total 131680
  2586  drwxr-xr-x   8 User1  staff       256 Jan 27 14:43 .
  2587  drwxr-xr-x  27 User1  staff       864 Jan 27 14:43 ..
  2588  -rw-r--r--   1 User1  staff      7121 Jan 27 14:43 config.json
  2589  -rw-r--r--   1 User1  staff      1346 Jan 27 14:43 custom.json
  2590  -rw-r--r--   1 User1  staff     62532 Jan 27 14:43 license.json
  2591  -rwxr-xr-x   1 User1  staff  11336640 Jan 27 14:43 sbom-utility-darwin-amd64
  2592  -rwxr-xr-x   1 User1  staff  11146770 Jan 27 14:43 sbom-utility-darwin-arm64
  2593  -rwxr-xr-x   1 User1  staff  11495647 Jan 27 14:43 sbom-utility-linux-amd64
  2594  -rwxr-xr-x   1 User1  staff  11076025 Jan 27 14:43 sbom-utility-linux-arm64
  2595  -rwxr-xr-x   1 User1  staff  11416576 Jan 27 14:43 sbom-utility-windows-amd64
  2596  -rwxr-xr-x   1 User1  staff  10934272 Jan 27 14:43 sbom-utility-windows-arm64
  2597  ...
  2598  ```
  2599  
  2600  - *Please also note that the common `*.json` configuration files are also copied to the `release` directory.*
  2601  
  2602  ### Versioning
  2603  
  2604  to produce a release version you can set the following flags and invoke `go build` directly:
  2605  
  2606  ```bash
  2607  BINARY=sbom-utility
  2608  VERSION=latest
  2609  LDFLAGS=-ldflags "-X main.Version=${VERSION} -X main.Binary=${BINARY}"
  2610  $ go build ${LDFLAGS} -o ${BINARY}
  2611  ```
  2612  
  2613  **TODO**: Update the `Makefile's` `release` target to conditionally pull the release version from environment variable values and only uses the hardcoded values as defaults when not found in the runtime build environment.
  2614  
  2615  ---
  2616  
  2617  ## BOM References
  2618  
  2619  ### Software-Bill-of-Materials (SBOM)
  2620  
  2621  - [NTIA - SBOM Minimum Requirements](https://www.ntia.doc.gov/blog/2021/ntia-releases-minimum-elements-software-bill-materials)
  2622  - [CISA - Software Bill of Materials (SBOM)](https://www.cisa.gov/sbom)
  2623  - [FOSSA - Software Bill Of Materials: Formats, Use Cases, and Tools](https://fossa.com/blog/software-bill-of-materials-formats-use-cases-tools/)
  2624  
  2625  #### Guides
  2626  
  2627  - [FOSSA](https://fossa.com/)
  2628    - *["A Practical Guide to CycloneDX"](https://fossa.com/cyclonedx)*
  2629  
  2630  ### CycloneDX
  2631  
  2632  - [CycloneDX Specification Overview](https://cyclonedx.org/specification/overview/)
  2633  - GitHub: https://github.com/CycloneDX
  2634    - Specifications (by branch): https://github.com/CycloneDX/specification
  2635    - Schemas (all versions): https://github.com/CycloneDX/specification/tree/master/schema
  2636    - Examples: https://github.com/CycloneDX/sbom-examples
  2637  - CycloneDX Tool Center : https://cyclonedx.org/tool-center/
  2638  
  2639  #### CycloneDX use cases
  2640  
  2641  - [CycloneDX Use Cases](https://cyclonedx.org/use-cases/) (comprehensive), including:
  2642    - [Inventory](https://cyclonedx.org/use-cases/#inventory)
  2643    - [License Compliance](https://cyclonedx.org/use-cases/#license-compliance)
  2644    - [Known Vulnerabilities](https://cyclonedx.org/use-cases/#known-vulnerabilities)
  2645  
  2646  - [CycloneDX Vulnerability Exploitability Exchange (VEX) format Overview](https://cyclonedx.org/capabilities/vex/)
  2647    - Examples: https://github.com/CycloneDX/bom-examples/tree/master/VEX
  2648  
  2649  ### SPDX
  2650  
  2651  - GitHub: https://github.com/spdx
  2652    - Specifications (by branch): https://github.com/spdx/spdx-spec
  2653    - Schemas (by branch):
  2654      - [v2.3.1](https://github.com/spdx/spdx-spec/tree/development/v2.3.1/schemas)
  2655      - [v2.3](https://github.com/spdx/spdx-spec/tree/development/v2.3/schemas)
  2656      - [v2.2.2](https://github.com/spdx/spdx-spec/tree/development/v2.2.2/schemas)
  2657    - SPDX Examples: [https://github.com/spdx/spdx-examples](https://github.com/spdx/spdx-examples)
  2658  
  2659  - Tools
  2660    - [SPDX Online Tool](https://tools.spdx.org/app/)
  2661      - **Note** Used the [convert](https://tools.spdx.org/app/convert/) tool to convert SPDX examples from `.tv` format to `.json`; however, conversion of [`example6-bin.spdx`](https://github.com/spdx/spdx-examples/blob/master/example6/spdx/example6-bin.spdx) resulted in an error.