Dependency scanning by using SBOM

Tier: Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated Status: Experiment
History
This feature uses an Experimental analyzer. For more information, see the history. This feature is available for testing, but not ready for production use.

Dependency scanning using CycloneDX SBOM analyzes your application’s dependencies for known vulnerabilities. All dependencies are scanned, including transitive dependencies, also known as nested dependencies.

Dependency scanning is often considered part of Software Composition Analysis (SCA). SCA can contain aspects of inspecting the items your code uses. These items typically include application and system dependencies that are almost always imported from external sources, rather than sourced from items you wrote yourself.

Dependency scanning can run in the development phase of your application’s lifecycle. Every time a pipeline produces an SBOM report, security findings are identified and compared between the source and target branches. Findings and their severity are listed in the merge request, enabling you to proactively address the risk to your application, before the code change is committed. Security findings can also be identified outside a pipeline by Continuous Vulnerability Scanning.

GitLab offers both dependency scanning and container scanning to ensure coverage for all of these dependency types. To cover as much of your risk area as possible, we encourage you to use all of our security scanners. For a comparison of these features, see Dependency Scanning compared to Container Scanning.

Supported package types

The vulnerability scanning of SBOM files is performed in GitLab by the same scanner used by Continuous Vulnerability Scanning. In order for security scanning to work for your package manager, advisory information must be available for the components present in the SBOM report.

See Supported package types.

Dependency detection workflow

The dependency detection workflow is as follows:

  1. The application to be scanned provides a CycloneDX SBOM report or creates one by enabling the GitLab Dependency Scanning analyzer.
  2. GitLab checks each of the dependencies listed in the SBOM against the GitLab Advisory Database.
  3. If the SBOM report is declared by a CI/CD job on the default branch: vulnerabilities are created, and can be seen in the vulnerability report.

    If the SBOM report is declared by a CI/CD job on a non-default branch: no vulnerability scanning takes place. Improvement to the feature is being tracked in Epic 14636 so that security findings are created, and can be seen in the pipeline security tab and MR security widget.

Configuration

  • Enable the dependency scanning analyzer to generate a CycloneDX SBOM containing your application’s dependencies. Once this report is uploaded to GitLab, the dependencies are scanned for known vulnerabilities.
  • You can adjust the analyzer behavior by configuring the CI/CD component’s inputs.

For a list of languages and package managers supported by the analyzer, see supported files.

After a CycloneDX SBOM report is uploaded, GitLab automatically scans all supported package types present in the report.

Enabling the analyzer

The Dependency Scanning analyzer produces a CycloneDX SBOM report compatible with GitLab. If your application can’t generate such a report, you can use the GitLab analyzer to produce one.

Prerequisites:

  • A supported lock file or dependency graph must exist in the repository or must be passed as an artifact to the dependency-scanning job.
  • The component’s stage is required in the .gitlab-ci.yml file.
  • With self-managed runners you need a GitLab Runner with the docker or kubernetes executor.
    • If you’re using SaaS runners on GitLab.com, this is enabled by default.

To enable the analyzer, use the main dependency scanning CI/CD component:

include:
  - component: $CI_SERVER_FQDN/components/dependency-scanning/main@0

Language-specific instructions

If your project doesn’t have a supported lock file dependency graph committed to its repository, you need to provide one.

The examples below show how to create a file that is supported by the GitLab analyzer for popular languages and package managers.

Gradle

To enable the CI/CD component on a Gradle project:

  1. Edit the build.gradle or build.gradle.kts to use the gradle-dependency-lock-plugin.
  2. Configure the .gitlab-ci.yml file to generate the dependencies.lock artifacts, and pass them to the dependency-scanning job.

The following example demonstrates how to configure the component for a Gradle project.

stages:
  - build
  - test

# Define the image that contains Java and Gradle
image: gradle:8.0-jdk11

include:
  - component: $CI_SERVER_FQDN/components/dependency-scanning/main@0

build:
  # Running in the build stage ensures that the dependency-scanning job
  # receives the maven.graph.json artifacts.
  stage: build
  script:
    - gradle generateLock saveLock
    - gradle assemble
  # generateLock saves the lock file in the build/ directory of a project
  # and saveLock copies it into the root of a project. To avoid duplicates
  # and get an accurate location of the dependency, use find to remove the
  # lock files in the build/ directory only.
  after_script:
    - find . -path '*/build/dependencies.lock' -print -delete
  # Collect all dependencies.lock artifacts and pass them onto jobs
  # in sequential stages.
  artifacts:
    paths:
      - "**/dependencies.lock"

Maven

The following example .gitlab-ci.yml demonstrates how to enable the CI/CD component on a Maven project. The dependency graph is output as a job artifact in the build stage, before dependency scanning runs.

stages:
  - build
  - test

image: maven:3.9.9-eclipse-temurin-21

include:
  - component: $CI_SERVER_FQDN/components/dependency-scanning/main@0

build:
  # Running in the build stage ensures that the dependency-scanning job
  # receives the maven.graph.json artifacts.
  stage: build
  script:
    - mvn install
    - mvn dependency:tree -DoutputType=json -DoutputFile=maven.graph.json
  # Collect all maven.graph.json artifacts and pass them onto jobs
  # in sequential stages.
  artifacts:
    paths:
      - "**/*.jar"
      - "**/maven.graph.json"

Customizing analyzer behavior

The analyzer can be customized by configuring the CI/CD component’s inputs.

Output

The dependency scanning analyzer produces CycloneDX Software Bill of Materials (SBOM) for each supported lock file or dependency graph export detected.

CycloneDX Software Bill of Materials

  • Generally available in GitLab 15.7.

The dependency scanning analyzer outputs a CycloneDX Software Bill of Materials (SBOM) for each supported lock or dependency graph export it detects. The CycloneDX SBOMs are created as job artifacts.

The CycloneDX SBOMs are:

  • Named gl-sbom-<package-type>-<package-manager>.cdx.json.
  • Available as job artifacts of the dependency scanning job.
  • Uploaded as cyclonedx reports.
  • Saved in the same directory as the detected lock or dependency graph exports files.

For example, if your project has the following structure:

.
├── ruby-project/
│   └── Gemfile.lock
├── ruby-project-2/
│   └── Gemfile.lock
└── php-project/
    └── composer.lock

The following CycloneDX SBOMs are created as job artifacts:

.
├── ruby-project/
│   ├── Gemfile.lock
│   └── gl-sbom-gem-bundler.cdx.json
├── ruby-project-2/
│   ├── Gemfile.lock
│   └── gl-sbom-gem-bundler.cdx.json
└── php-project/
    ├── composer.lock
    └── gl-sbom-packagist-composer.cdx.json

Merging multiple CycloneDX SBOMs

You can use a CI/CD job to merge the multiple CycloneDX SBOMs into a single SBOM.

note
GitLab uses CycloneDX Properties to store implementation-specific details in the metadata of each CycloneDX SBOM, such as the location of dependency graph exports and lock files. If multiple CycloneDX SBOMs are merged together, this information is removed from the resulting merged file.

For example, the following .gitlab-ci.yml extract demonstrates how the Cyclone SBOM files can be merged, and the resulting file validated.

stages:
  - test
  - merge-cyclonedx-sboms

include:
  - component: $CI_SERVER_FQDN/components/dependency-scanning/main@0

merge cyclonedx sboms:
  stage: merge-cyclonedx-sboms
  image:
    name: cyclonedx/cyclonedx-cli:0.27.1
    entrypoint: [""]
  script:
    - find . -name "gl-sbom-*.cdx.json" -exec cyclonedx merge --output-file gl-sbom-all.cdx.json --input-files "{}" +
    # optional: validate the merged sbom
    - cyclonedx validate --input-version v1_6 --input-file gl-sbom-all.cdx.json
  artifacts:
    paths:
      - gl-sbom-all.cdx.json