Skip to main content

CycloneDX Application Analysis

Sonatype Lifecycle analysis has expanded support of the CycloneDX v1.5 standard, the industry’s most advanced software bill of materials (SBOM) format. An SBOM is a list of all packages and libraries included in your application. It’s the digital equivalent of a manufacturing bill of materials. Just as a bill of materials includes all sub-assemblies, the SBOM also includes transitive dependencies or your components’ dependencies. The SBOM makes it easy to see if any risky packages are included in an application.

Identification Source

The CycloneDX format can be used as an Identification Source in the Application Composition Report. Lifecycle scanners automatically incorporate discovered SBOMs in the following patterns.

The CycloneDX integration provides native component identification for many languages and formats. Find a complete list at the CycloneDX Tool Center. You may also upload SBOMs directly using the Third-Party Scan REST API.

Note

When no source is provided through the API or using the above filename prefix, "Third Party" is used as the Identification Source in the Application Composition Report.

Note

Fixed a bug where invalid SBOMs could be generated.

Additionally, if an SBOM is scanned and it is found to be invalid, then it will be rejected.

Component Identifiers, Package URL, and SHA-1 Hash

For libraries declared in the SBOM, Lifecycle scanners use the following priority when identifying components. An example of each is included below.

  1. Package URL (purl)

  2. SHA-1 Hashes

  3. Component Identifiers (group/scope/namespace, name, version)

Note

Note: In the unlikely case of the same component being found more than once in the sbom, only the data of the first component will be processed/shown.

Dependency Relationships

The CycloneDX 1.4+ format includes dependency graph information of the direct and transitive relationships between dependencies. The Lifecycle scanners include this information in the scan report and for the application dependency tree. See the Dependency Graph below.

Innersource Components

CycloneDX can be used to identifyInnersourcet 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. See the examples of a producer and consumer below.

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.

Note

Hashes included in the exported CycloneDX report will consist of a truncated (first 20 digits) sha-1 rather than the full hash.

Vulnerability Analysis Section

The CycloneDX 1.4+ format includes analysis information of the vulnerabilities. Sonatype Lifecycle scanners include this information starting with release 168.

Note

Information under the vulnerability analysis section will appear if it originally existed in the SBOM that was scanned for the same stage. If it did not exist, you can add the vulnerability analysis section in the original SBOM using the Vulnerability Analysis Details REST API.

Example SBOMs

XML (version 1.5) file content

<?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.5">
  <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>

JSON (version 1.5) file content

{
  "bomFormat" : "CycloneDX",
  "specVersion" : "1.5",
  "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",
            "responses": {
              "response": [
                "workaround_available",
                "update"
              ]
            },
            "detail": "Analysis Detail"
          },
          "affects": [
              {
                  "ref": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar"
              }
          ]
      }
  ]
}

Dependency Graph

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>

Innersource Producer

producer-bom.xml

<?xml version="1.0" encoding="UTF-8"?>
<bom version="1" xmlns="http://cyclonedx.org/schema/bom/1.5">
        <metadata>
                <component type="application" bom-ref="pkg:npm/producer@1.0.0">
                        <name>producer</name>
                        <version>1.0.0</version>
                </component>
        </metadata>
        <components>
                <component type="library" bom-ref="pkg:npm/some-awesome-component@1.0">
                        <name>some-awesome-component</name>
                        <version>1.0</version>
                        <purl>pkg:npm/some-awesome-component@1.0</purl>
                </component>
        </components>
        <dependencies>
                <dependency ref="pkg:npm/producer@1.0.0">
                        <dependency ref="pkg:npm/some-awesome-component@1.0"/>
                </dependency>
                <dependency ref="pkg:npm/some-awesome-component@1.0"/>
        </dependencies>
</bom>

Innersource Consumer

consumer-bom.xml Expand source

<?xml version="1.0" encoding="UTF-8"?>
<bom version="1" xmlns="http://cyclonedx.org/schema/bom/1.2">
        <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>
                        <version>1.0</version>
                        <purl>pkg:npm/some-awesome-component@1.0</purl>
                </component>
        </components>
        <dependencies>
                <dependency ref="pkg:npm/consumer@1.0.0">
                        <dependency ref="pkg:npm/producer@1.0"/>
                </dependency>
                <dependency ref="pkg:npm/producer@1.0">
                        <dependency ref="pkg:npm/some-awesome-component@1.0"/>
                </dependency>
                <dependency ref="pkg:npm/some-awesome-component@1.0"/>
        </dependencies>
</bom>

Analyze using the Jenkins plugin

By default, the Jenkins plugin will not evaluate the bom.xml. A custom Scan Target is needed.

Example Pipeline Script with Scan Patterns

nexusPolicyEvaluation iqApplication: 'SampApp', iqScanPatterns: [[scanPattern: '**/bom.xml'], [scanPattern: '**/*-bom.xml']], iqStage: 'build'

To find more information on how to configure Jenkins please go to Sonatype Platform Plugin for Jenkins

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 Sonatype for Bamboo Data Center.