CycloneDX Application Analysis
Sonatype Lifecycle analysis supports the CycloneDX standard, the industry’s most advanced software bill of materials (SBOM) format.
An SBOM is a list of parts (packages and libraries) included in the application. Just as a manufacturing bill of materials includes all sub-assemblies, the SBOM also includes the direct and transitive dependencies along with any internal components made by your organization.
Analyzing an SBOM
Any Sonatype scanner and most of the integrations will analyze SBOMs found in the root context of the application scan target when using the naming format listed below in the Identification Source section.
SBOMs may be targeted directly using the command line scanner (CLI), by uploading to the user interface, or by scripting using the Third-Party Scan REST API.
Any application scan may be exported as an SBOM in the CycloneDX and SPDX formats. Learn about more SBOM use cases from our SBOM guide.
CycloneDX provides many native application scanners on its repository. Find a complete list at the CycloneDX Tool Center.
Identification Source
The CycloneDX format is used as an identification source in the Application Composition Report. The prefix of the file name is used as the source. Third Party
is used as the identification source when no source is provided through the API or using the filename prefix.
bom.xml
<source>-bom.xml
<source>-bom.json
<public app id>_<version>_<timestamp>.cdx.<json|xml>
Sonatype scanners use the above naming formats to identify and analyze SBOMs within archives. Make sure your SBOM names follow this format when outputting them through third-party tools.
Component Identifiers, Package-URL, and SHA-1 Hash
For libraries declared in the SBOM, Lifecycle uses the following priority when identifying components. An example of each is included below. When a component is found more than once in the sbom, only the data of the first component will be processed/shown. Hashes included in the exported CycloneDX report will consist of a truncated (first 20 digits) SHA-1 rather than the full hash.
Package-URL (PURL)
SHA-1 Hashes
Component Identifiers (group/scope/namespace, name, version)
Dependency Relationships
The CycloneDX 1.4+ format includes dependency graph information on the direct and transitive relationships between dependencies. The Lifecycle scanners include this information in the scan report and for the application dependency tree.
Components at the first level of listed dependencies in the SBOM are identified during an analysis. SBOMs with nested components will pass validation; however, nested components are not supported and are ignored during the analysis.
See the Dependency Graph below.
Innersource Components
CycloneDX can be used to identify Innersource producers as well as when they are consumed by other applications as dependencies. Similarly, this can be used to identify proprietary components. When processing the report, Lifecycle will use the identity information provided in the CycloneDX file when the component is unknown; greatly reducing the number of component unknown violations. This would include in the report any security and license data provided in the SBOM.
Sonatype properties in SBOMs
Software Bill of Materials generated by Sonatype includes Sonatype-specific metadata under the Sonatype namespace taxonomy.
Property | Description |
---|---|
| The source of the identity information for the component. This is either |
| Verify when the comparison of a component to known components is or is not a match in one of the following ways: |
| The filename where the identified component is found |
| An internal identifier used by Sonatype made from the first 20 chars of either the component's sha1 hash or a synthetic hash of the component's coordinates. |
Application Reports
In conjunction with using CycloneDX to do the application analysis, you can also export any application report in Lifecycle to the CycloneDX format.
The Options Dropdown from the Scan Report
From the CycloneDX REST API
Vulnerability Analysis Section
The CycloneDX 1.4+ format includes analysis information of the vulnerabilities. Sonatype imports the vulnerability analysis found in this section to include in the scan report.
The Sonatype Data Services team frequently evaluates vulnerabilities that enter our systems for accuracy and repeatability. They may determine a vulnerability is not applicable and therefore do not report the vulnerability against the component in our products. For these reasons, we favor reporting data coming from Sonatype Data Services over content reported from third-party sources to reduce the noise reported to development teams and used for enforcement.
The SBOM uses our vulnerability data for every known component in the Sonatype Data Services. Imported vulnerability data is not included.
For components not found in the Sonatype Data Services, the vulnerability and license details are sourced from the originally imported SBOM.
Custom Vulnerability Information
You may add vulnerability information to the SBOM using the Vulnerability Analysis Details REST API.
<?xml version="1.0" encoding="UTF-8"?> <bom serialNumber="urn:uuid:cb3c8aae-d8a0-4ef5-a40d-de537161f948" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6"> <metadata> <timestamp>2023-01-12T14:46:58Z</timestamp> <component type="application" bom-ref="pkg:maven/org.example/ACME-Test@1.0-SNAPSHOT?type=pom"> <group>org.example</group> <name>ACME-Test</name> <version>1.0-SNAPSHOT</version> <purl>pkg:maven/org.example/ACME-Test@1.0-SNAPSHOT?type=pom</purl> </component> </metadata> <components> <component type="library" bom-ref="pkg:maven/javax.inject/javax.inject@1?type=jar"> <group>javax.inject</group> <name>javax.inject</name> <version>1</version> <hashes> <hash alg="SHA-1">6975da39a7040257bd51d21a231b76c915872d38</hash> </hashes> <licenses> <license> <id>Apache-2.0</id> </license> </licenses> <purl>pkg:maven/javax.inject/javax.inject@1?type=jar</purl> </component> <component type="library" bom-ref="pkg:maven/commons-io/commons-io@2.6?type=jar"> <group>commons-io</group> <name>commons-io</name> <version>2.6</version> <licenses> <license> <id>Apache-2.0</id> </license> </licenses> <purl>pkg:maven/commons-io/commons-io@2.6?type=jar</purl> <modified>false</modified> </component> <component type="library" bom-ref="pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar"> <group>com.fasterxml.jackson.core</group> <name>jackson-databind</name> <version>2.13.4</version> <hashes> <hash alg="SHA-1">98b0edfa8e4084078f10b7b356c300ded4a71491</hash> </hashes> <licenses> <license> <id>Apache-2.0</id> </license> </licenses> <purl>pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar</purl> </component> <component type="library" bom-ref="pkg:maven/org.example/ACME-data@1.0-SNAPSHOT?type=jar"> <group>org.example</group> <name>ACME-data</name> <version>1.0-SNAPSHOT</version> <purl>pkg:maven/org.example/ACME-data@1.0-SNAPSHOT?type=jar</purl> </component> </components> <dependencies> <dependency ref="pkg:maven/org.example/ACME-Test@1.0-SNAPSHOT?type=pom"> <dependency ref="pkg:maven/org.example/ACME-data@1.0-SNAPSHOT?type=jar"/> <dependency ref="pkg:maven/commons-io/commons-io@2.6?type=jar"/> </dependency> <dependency ref="pkg:maven/org.example/ACME-data@1.0-SNAPSHOT?type=jar"> <dependency ref="pkg:maven/javax.inject/javax.inject@1?type=jar"/> <dependency ref="pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar"/> <dependency ref="pkg:maven/commons-io/commons-io@2.6?type=jar"/> </dependency> <dependency ref="pkg:maven/javax.inject/javax.inject@1?type=jar"/> <dependency ref="pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar"/> <dependency ref="pkg:maven/commons-io/commons-io@2.6?type=jar"/> </dependencies> <vulnerabilities> <vulnerability> <id>CVE-2022-42003</id> <source> <name>NVD</name> <url>http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-42003</url> </source> <ratings> <rating> <source> <name>NVD</name> </source> <score>7.5</score> <severity>critical</severity> <method>CVSSv3</method> <vector>CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H</vector> </rating> </ratings> <cwes> <cwe>502</cwe> </cwes> <analysis> <state>resolved_with_pedigree</state> <justification>requires_environment</justification> <responses> <response>workaround_available</response> <response>update</response> </responses> <detail>Analysis Detail</detail> </analysis> <affects> <target> <ref>pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar</ref> </target> </affects> </vulnerability> </vulnerabilities> </bom>
{ "bomFormat" : "CycloneDX", "specVersion" : "1.6", "serialNumber" : "urn:uuid:d069c08a-1e5b-4de2-b6d7-509964190ea7", "version" : 1, "metadata" : { "component" : { "group" : "org.example", "name" : "ACME-Test", "version" : "1.0-SNAPSHOT", "licenses" : [ ], "purl" : "pkg:maven/org.example/ACME-Test@1.0-SNAPSHOT?type=pom", "type" : "library", "bom-ref" : "pkg:maven/org.example/ACME-Test@1.0-SNAPSHOT?type=pom" } }, "components" : [ { "publisher" : "The Apache Software Foundation", "group" : "commons-io", "name" : "commons-io", "version" : "2.6", "hashes" : [ { "alg" : "SHA-1", "content" : "815893df5f31da2ece4040fe0a12fd44b577afaf" } ], "licenses" : [ { "license" : { "id" : "Apache-2.0" } } ], "purl" : "pkg:maven/commons-io/commons-io@2.6?type=jar", "type" : "library", "bom-ref" : "pkg:maven/commons-io/commons-io@2.6?type=jar" }, { "group" : "org.example", "name" : "ACME-data", "version" : "1.0-SNAPSHOT", "licenses" : [ ], "purl" : "pkg:maven/org.example/ACME-data@1.0-SNAPSHOT?type=jar", "type" : "library", "bom-ref" : "pkg:maven/org.example/ACME-data@1.0-SNAPSHOT?type=jar" }, { "group" : "javax.inject", "name" : "javax.inject", "version" : "1", "description" : "The javax.inject API", "hashes" : [ { "alg" : "SHA-1", "content" : "6975da39a7040257bd51d21a231b76c915872d38" } ], "licenses" : [ { "license" : { "id" : "Apache-2.0" } } ], "purl" : "pkg:maven/javax.inject/javax.inject@1?type=jar", "type" : "library", "bom-ref" : "pkg:maven/javax.inject/javax.inject@1?type=jar" }, { "publisher" : "FasterXML", "group" : "com.fasterxml.jackson.core", "name" : "jackson-databind", "version" : "2.13.4", "hashes" : [ { "alg" : "SHA-1", "content" : "98b0edfa8e4084078f10b7b356c300ded4a71491" } ], "licenses" : [ { "license" : { "id" : "Apache-2.0" } } ], "purl" : "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar", "type" : "library", "bom-ref" : "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar" } ], "dependencies" : [ { "ref" : "pkg:maven/org.example/ACME-Test@1.0-SNAPSHOT?type=pom", "dependsOn" : [ "pkg:maven/commons-io/commons-io@2.6?type=jar", "pkg:maven/org.example/ACME-data@1.0-SNAPSHOT?type=jar" ] }, { "ref" : "pkg:maven/commons-io/commons-io@2.6?type=jar", "dependsOn" : [ ] }, { "ref" : "pkg:maven/org.example/ACME-data@1.0-SNAPSHOT?type=jar", "dependsOn" : [ "pkg:maven/javax.inject/javax.inject@1?type=jar", "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar", "pkg:maven/commons-io/commons-io@2.6?type=jar" ] }, { "ref" : "pkg:maven/javax.inject/javax.inject@1?type=jar", "dependsOn" : [ ] }, { "ref" : "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar", "dependsOn" : [ ] } ], "vulnerabilities": [ { "id": "CVE-2022-42003", "source": { "name": "NVD", "url": "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-42003" }, "ratings": [ { "source": { "name": "NVD" }, "score": 7.5, "severity": "critical", "method": "CVSSv3", "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" } ], "cwes": [ 502 ], "analysis": { "state": "resolved_with_pedigree", "justification": "requires_environment", "response": [ "workaround_available", "update" ], "detail": "Analysis Detail" }, "affects": [ { "ref": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar" } ] } ] }
dependency-bom.xml
<?xml version="1.0" encoding="UTF-8"?> <bom xmlns="http://cyclonedx.org/schema/bom/1.5" version="1"> <metadata> <component type="application" bom-ref="acme-app"> <name>Acme Application</name> <version>9.1.1</version> <purl>pkg:maven/org.acme/acme-app@9.1.1?type=jar</purl> </component> </metadata> <components> <component type="framework" bom-ref="pkg:maven/org.acme/web-framework@1.0.0?type=jar"> <group>org.acme</group> <name>web-framework</name> <version>1.0.0</version> <purl>pkg:maven/org.acme/web-framework@1.0.0?type=jar</purl> </component> <component type="library" bom-ref="pkg:maven/org.acme/persistence@3.1.0?type=jar"> <group>org.acme</group> <name>persistence</name> <version>3.1.0</version> <purl>pkg:maven/org.acme/persistence@3.1.0?type=jar</purl> </component> <component type="library" bom-ref="pkg:maven/org.acme/common-util@3.0.0?type=jar"> <group>org.acme</group> <name>common-util</name> <version>3.0.0</version> <purl>pkg:maven/org.acme/common-util@3.0.0?type=jar</purl> </component> </components> <dependencies> <dependency ref="acme-app"> <dependency ref="pkg:maven/org.acme/web-framework@1.0.0?type=jar"/> <dependency ref="pkg:maven/org.acme/persistence@3.1.0?type=jar"/> </dependency> <dependency ref="pkg:maven/org.acme/web-framework@1.0.0?type=jar"> <dependency ref="pkg:maven/org.acme/common-util@3.0.0?type=jar"/> </dependency> <dependency ref="pkg:maven/org.acme/persistence@3.1.0?type=jar"> <dependency ref="pkg:maven/org.acme/common-util@3.0.0?type=jar"/> </dependency> <dependency ref="pkg:maven/org.acme/common-util@3.0.0?type=jar"/> </dependencies> </bom>
producer-bom.xml
<?xml version="1.0" encoding="UTF-8"?> <bom version="1" xmlns="http://cyclonedx.org/schema/bom/1.6"> <metadata> <component type="application" bom-ref="pkg:generic/producer-component@1.0.0"> <name>producer-component</name> <version>1.0.0</version> </component> </metadata> <components> <component type="library" bom-ref="pkg:generic/some-awesome-component@1.0"> <name>some-awesome-component</name> <version>1.0</version> <purl>pkg:generic/some-awesome-component@1.0</purl> </component> </components> <dependencies> <dependency ref="pkg:generic/producer-component@1.0.0"> <dependency ref="pkg:generic/some-awesome-component@1.0" /> </dependency> <dependency ref="pkg:generic/some-awesome-component@1.0" /> </dependencies> </bom>
consumer-bom.xml
<?xml version="1.0" encoding="UTF-8"?> <bom version="1" xmlns="http://cyclonedx.org/schema/bom/1.6"> <metadata> <component type="application" bom-ref="pkg:npm/consumer@1.0.0"> <name>consumer</name> <version>1.0.0</version> </component> </metadata> <components> <component type="library" bom-ref="pkg:npm/producer@1.0"> <name>producer</name> <version>1.0</version> <purl>pkg:npm/producer@1.0</purl> </component> <component type="library" bom-ref="pkg:npm/some-awesome-component@1.0"> <name>some-awesome-component</name>
Analyze using the CycloneDX maven plugin
The CycloneDX maven plugin may be used to generate an SBOM to include when analyzing your application. Following is a sample request to make the BOM and set the name of the bom using the outputName
.
mvn org.cyclonedx:cyclonedx-maven-plugin:2.8.2:makeAggregateBom -DoutputName=cyclonedx-bom
This will generate cyclonedx-bom.xml and cyclonedx-bom.json which are compatible with the Lifecycle scanners.
The CycloneDX output may be included directly in the project pom.xml to be picked up by the Lifecycle Analysis automatically.
This example includes the CycloneDX generation in the pom.xml plugins. Note the outputName
is used in the project.artifactId
to generate the name of the BOM file.
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<projectType>library</projectType>
<schemaVersion>1.5</schemaVersion>
<includeBomSerialNumber>true</includeBomSerialNumber>
<includeCompileScope>true</includeCompileScope>
<includeProvidedScope>true</includeProvidedScope>
<includeRuntimeScope>true</includeRuntimeScope>
<includeSystemScope>true</includeSystemScope>
<includeTestScope>false</includeTestScope>
<includeLicenseText>false</includeLicenseText>
<outputReactorProjects>true</outputReactorProjects>
<outputFormat>all</outputFormat>
<outputName>${project.artifactId}-bom</outputName>
<outputDirectory>${project.build.directory}</outputDirectory>
<verbose>false</verbose>
</configuration>
</plugin>
Learn more from the CycloneDX maven plugin documentation.
Analyze using the Jenkins plugin
By default, the Jenkins plugin will not evaluate the bom.xml. A custom scan target is needed.
nexusPolicyEvaluation iqApplication: 'SampApp', iqScanPatterns: [ [scanPattern: '**/bom.xml'], [scanPattern: '**/*-bom.xml'] ], iqStage: 'build'
More at Jenkins - Lifecycle
Analyze using the Bamboo plugin
Bamboo Scan Targets control what files are examined. To evaluate CycloneDX, add bom.xml to the scan targets via a comma-separated list e.g.
Example Bamboo Scan Patterns
**/bom.xml,**/*-bom.xml
To find more information on how to configure Bamboo please go to Bamboo Data Center.