CycloneDX Application Analysis

Nexus Lifecycle analysis has expanded support of the CycloneDX v1.4 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.

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.

NEW IN RELEASE 138

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: 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.

NEW IN RELEASE 133

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 example 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.  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.

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

Example SBOMs

XML (version 1.4) 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.4">
  <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>
      <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.4) file content

{
  "bomFormat" : "CycloneDX",
  "specVersion" : "1.4",
  "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
          ],
          "affects": [
              {
                  "ref": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4?type=jar"
              }
          ]
      }
  ]
}

Dependency Graph

<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.3" 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

<?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/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

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

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

To find more information on how to configure Jenkins please go to the Nexus 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.

**/bom.xml,**/*-bom.xml

To find more information on how to configure Bamboo please go to the Nexus IQ for Bamboo.