CloudBees action: Scan with Black Duck SCA

4 minute read

Use this action to scan repositories for dependency vulnerabilities with the Black Duck Software Composition Analysis (SCA) scanner. You can also use the action output as a quality gate for the next step or job in your workflow.

Black Duck is a software composition analysis (SCA) scanning solution that helps organizations manage risks associated with open-source software in terms of security, license compliance, and code quality.

Add a Black Duck scan to your workflows in CloudBees platform to:

  • Detect open-source and third-party dependencies in software, source code, and artifacts with multiple analysis techniques.

  • Identify code vulnerabilities and receive timely security advisories.

  • Gain insight into security risks and how to fix vulnerabilities.

CloudBees platform enables you to run a Black Duck scan either implicitly or explicitly.

Explicit and implicit scan types

An implicit scan is automatically triggered, and an explicit scan is one you configure to be invoked in a step of your workflow. To learn more about the differences between explicit and implicit scans, refer to CloudBees actions.

To set up implicit scanning, refer to Code and binary security analysis.

How the scanner works

The Black Duck SCA scanner architectural components are:

  • Client-side: The Black Duck Detect scanning tool, the Signature Scanner command-line tool, and the REST API.

  • Server-side: The Black Duck server.

  • Data center: The Black Duck KnowledgeBase open-source software database.

The scanning process is as follows:

  1. The Black Duck Detect tool is used to authenticate and initiate the code scan.

  2. Codebases are scanned on the client side.

  3. The scan data is uploaded to the Black Duck server with the Detect tool. The completed scan data does not contain any source code, to maintain your code security. The completed scan contains only file and directory signatures, and information derived from package management files.

  4. The scan data is sent to the Black Duck KnowledgeBase, and open-source components in your code are matched and identified. The matching/identification process is based on your package manager data and SHA1 hashes created by the Signature Scanner when it scans your files and directories.

  5. The REST API is used to fetch the bearer token and retrieve the scanning results.

  6. The matched open-source components are reported as a viewable Bill of Materials that contains the associated security, licensing, and operational risks of the discovered components.

For more information about the Black Duck SCA scanner, refer to the Black Duck documentation.
All CloudBees action repositories are listed at CloudBees, Inc. on GitHub.

Inputs

Table 1. Input details
Input name Data type Required? Description

server-url

String

Yes

The Black Duck server URL.

api-token

String

Yes

The Black Duck client secret.

ref

String

Yes

Specify the ref to be checked out and archived.

project-name

String

No

The Black Duck project name.

project-version

String

No

The Black Duck project version.

detect-cli-params

String

No

Outputs

Table 2. Output details
Output name Data type Description

critical-count

String

The number of Critical security findings discovered during the scan.

very-high-count

String

The number of Very high security findings discovered during the scan.

high-count

String

The number of High security findings discovered during the scan.

medium-count

String

The number of Medium security findings discovered during the scan.

low-count

String

The number of Low security findings discovered during the scan.

Usage examples

Basic usage

The following is a basic usage example for this action:

- name: Scan with Black Duck SCA uses: cloudbees-io/blackduck-sca-scan-dependency@v2 with: server-url: ${{ vars.BLACK_DUCK_URL }} api-token: ${{ secrets.BLACK_DUCK_TOKEN }} ref: main

Using Black Duck Detect properties

In the following example, the Black Duck Detect properties logging.level.detect and blackduck.offline.mode are specified:

- name: Scan with Black Duck SCA with params uses: cloudbees-io/blackduck-sca-scan-dependency@v2 with: server-url: ${{ vars.BLACK_DUCK_URL }} api-token: ${{ secrets.BLACK_DUCK_TOKEN }} ref: main project-name: 'my-project' project-version: '0.0.1' detect-cli-params: '--logging.level.detect=DEBUG --blackduck.offline.mode=false'

Scan a C language repository with Black Duck

The following CloudBees platform workflow example scans a C++ repository with Black Duck.

name: black-duck-scan kind: workflow apiVersion: automation.cloudbees.io/v1alpha1 on: push: branches: - main permissions: scm-token-own: read scm-token-org: read id-token: write jobs: blackduck-scan: steps: - name: Check out C++ source code uses: cloudbees-io/checkout@v1 - name: Black Duck scan on C++ code uses: cloudbees-io/blackduck-sca-scan-dependency@v2 with: server-url: 'https://blackduck.example.com' api-token: ${{ secrets.BLACK_DUCK_API_TOKEN }} project-name: 'my-cpp-scan-project' project-version: '0.0.2' detect-cli-params: '--detect.clang.compile.commands.path=./compile_commands.json'

For all C language scans, be sure to specify the compilation database file via detect-cli-params: '--detect.clang.compile.commands.path=./compile_commands.json'.

If you do not add the compilation database file, the Black Duck scan may:

  • Miss dependencies and be unable to resolve include paths and linked libraries.

  • Perform incomplete analyses and not detect all components and vulnerabilities.

  • Produce reduced accuracy due to a limited understanding of your project’s build configuration.

  • Return potential false positives or missed security issues.

Using the action output

Access the output values in downstream steps and jobs using the outputs context.

Use the output in your workflow as follows, where <action_step_ID> is the action step ID, and <severity> is an output parameter name, such as critical-count:

${{steps.<action_step_ID>.outputs.<severity>}}

The following example uses the action output in a downstream step of the same job:

name: my-workflow kind: workflow apiVersion: automation.cloudbees.io/v1alpha1 on: push: branches: - main permissions: scm-token-own: read scm-token-org: read id-token: write jobs: black-duck-scan-job: steps: - name: check out source code uses: cloudbees-io/checkout@v1 - id: black-duck-step name: black duck scan uses: cloudbees-io/blackduck-sca-scan-dependency@v2 - name: source dir examine uses: docker://golang:1.20.3-alpine3.17 shell: sh run: | ls -latR /cloudbees/workspace - id: print-outputs-from-black-duck-step name: print outputs from upstream black-duck step uses: docker://alpine:latest run: | #printing all outputs echo "Outputs from upstream black-duck step:" echo "Critical count: ${{steps.black-duck-step.outputs.critical-count}}" echo "Very high count: ${{steps.black-duck-step.outputs.very-high-count}}" echo "High count: ${{steps.black-duck-step.outputs.high-count}}" echo "Medium count: ${{steps.black-duck-step.outputs.medium-count}}" echo "Low count: ${{steps.black-duck-step.outputs.low-count}}"

The following example uses the action output in a downstream job:

name: my-workflow kind: workflow apiVersion: automation.cloudbees.io/v1alpha1 on: push: branches: - main permissions: scm-token-own: read scm-token-org: read id-token: write jobs: job1: outputs: black-duck-job-output-critical: ${{ steps.black-duck-step.outputs.critical-count }} black-duck-job-output-very-high: ${{ steps.black-duck-step.outputs.very-high-count }} black-duck-job-output-high: ${{ steps.black-duck-step.outputs.high-count }} black-duck-job-output-medium: ${{ steps.black-duck-step.outputs.medium-count }} black-duck-job-output-low: ${{ steps.black-duck-step.outputs.low-count }} steps: - name: check out source code uses: cloudbees-io/checkout@v1 with: repository: my-gh-repo-org/my-repo ref: main token: ${{ secrets.GIT_PAT }} - id: black-duck-step name: black duck scan uses: cloudbees-io/blackduck-sca-scan-dependency@v2 with: server-url: https://blackduck.example.com api-token: ${{ secrets.BLACK_DUCK_API_TOKEN }} project-name: my-project project-version: 0.0.1 ref: main job2: needs: job1 steps: - id: print-outputs-from-job1 name: print outputs from upstream job1 uses: docker://alpine:latest run: | # Printing all outputs echo "Outputs from upstream Black Duck job:" echo "Critical count: ${{ needs.job1.outputs.black-duck-job-output-critical }}" echo "Very high count: ${{ needs.job1.outputs.black-duck-job-output-very-high }}" echo "High count: ${{ needs.job1.outputs.black-duck-job-output-high }}" echo "Medium count: ${{ needs.job1.outputs.black-duck-job-output-medium }}" echo "Low count: ${{ needs.job1.outputs.black-duck-job-output-low }}"

Scan a GitHub Actions workflow explicitly with Black Duck

If you are using a GitHub Actions workflow rather than a CloudBees platform workflow, explicitly scan with the GHA Black Duck action to scan and publish to CloudBees platform.