History
dependency_scanning_using_sbom_reports
.0.4.0
in GitLab 17.5 with support for the lockfile-based Dependency Scanning analyzer.dependency_scanning_using_sbom_reports
removed in GitLab 17.10.Dependency scanning using CycloneDX SBOM analyzes your application’s dependencies for known vulnerabilities. All dependencies are scanned, including transitive 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 for reported SBOM components are also identified by Continuous Vulnerability Scanning when new security advisories are published, independently from CI/CD pipelines.
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.
Getting startedEnable the Dependency Scanning using SBOM feature with one of the following options:
latest
Dependency Scanning CI/CD template Dependency-Scanning.latest.gitlab-ci.yml
to enable a GitLab provided analyzer.
DS_ENFORCE_NEW_ANALYZER
to true
.dependency-scanning
job in pipelines.latest
template to enable a GitLab provided analyzer.
DS_ENFORCE_NEW_ANALYZER
to true
.dependency-scanning
job in pipelines.You should use the new Dependency Scanning analyzer. For details, see Enabling the analyzer. If instead you use the (deprecated) Gemnasium analyzer, refer to the enablement instructions for the legacy Dependency Scanning feature.
Enabling the analyzerThe 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.
Share any feedback on the new Dependency Scanning analyzer in this feedback issue.
Prerequisites:
dependency-scanning
job..gitlab-ci.yml
file.docker
or kubernetes
executor.
To enable the analyzer, you must:
Use either the latest
Dependency Scanning CI/CD template Dependency-Scanning.latest.gitlab-ci.yml
and enforce the new Dependency Scanning analyzer by setting the CI/CD variable DS_ENFORCE_NEW_ANALYZER
to true
.
include:
- template: Jobs/Dependency-Scanning.latest.gitlab-ci.yml
variables:
DS_ENFORCE_NEW_ANALYZER: 'true'
Use the Scan Execution Policies with the latest
template and enforce the new Dependency Scanning analyzer by setting the CI/CD variable DS_ENFORCE_NEW_ANALYZER
to true
.
Use the Dependency Scanning CI/CD component
include:
- component: $CI_SERVER_FQDN/components/dependency-scanning/main@0
Trigger files create a dependency-scanning
CI/CD job when using the latest Dependency Scanning CI template. The analyzer does not scan these files. Your project can be supported if you use a trigger file to build a supported lock file.
*.csproj
, *.vbproj
Java pom.xml
Java/Kotlin build.gradle
, build.gradle.kts
Python requirements.pip
, Pipfile
, requires.txt
, setup.py
Scala build.sbt
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.
GoIf your project provides only a go.mod
file, the Dependency Scanning analyzer can still extract the list of components. However, dependency path information is not available. Additionally, you might encounter false positives if there are multiple versions of the same module.
To benefit from improved component detection and feature coverage, you should provide a go.graph
file generated using the go mod graph
command from the Go toolchain.
The following example .gitlab-ci.yml
demonstrates how to enable the CI/CD component with dependency path support on a Go project. The dependency graph is output as a job artifact in the build
stage, before dependency scanning runs.
stages:
- build
- test
include:
- component: $CI_SERVER_FQDN/components/dependency-scanning/main@0
go:build:
stage: build
image: "golang:latest"
script:
- "go mod tidy"
- "go build ./..."
- "go mod graph > go.graph"
artifacts:
when: on_success
access: developer
paths: ["**/go.graph"]
Gradle
For Gradle projects use either of the following methods to create a dependency graph.
This method gives information about dependencies which are direct.
To enable the CI/CD component on a Gradle project:
build.gradle
or build.gradle.kts
to use the gradle-dependency-lock-plugin or use an init script..gitlab-ci.yml
file to generate the dependencies.lock
and dependencies.direct.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
image: gradle:8.0-jdk11
include:
- component: $CI_SERVER_FQDN/components/dependency-scanning/main@0
generate nebula lockfile:
# Running in the build stage ensures that the dependency-scanning job
# receives the scannable artifacts.
stage: build
script:
- |
cat << EOF > nebula.gradle
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:12.7.1'
}
}
allprojects {
apply plugin: nebula.plugin.dependencylock.DependencyLockPlugin
}
EOF
./gradlew --init-script nebula.gradle -PdependencyLock.includeTransitives=true -PdependencyLock.lockFile=dependencies.lock generateLock saveLock
./gradlew --init-script nebula.gradle -PdependencyLock.includeTransitives=false -PdependencyLock.lockFile=dependencies.direct.lock generateLock saveLock
# 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 generated artifacts and pass them onto jobs in sequential stages.
artifacts:
paths:
- '**/dependencies*.lock'
- '**/dependencies*.lock'
HtmlDependencyReportTask
This method gives information about dependencies which are both transitive and direct.
The HtmlDependencyReportTask is an alternative way to get the list of dependencies for a Gradle project (tested with gradle
versions 4 through 8). To enable use of this method with dependency scanning the artifact from running the gradle htmlDependencyReport
task needs to be available.
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:
stage: build
script:
- gradle --init-script report.gradle htmlDependencyReport
# The gradle task writes the dependency report as a javascript file under
# build/reports/project/dependencies. Because the file has an un-standardized
# name, the after_script finds and renames the file to
# `gradle-html-dependency-report.js` copying it to the same directory as
# `build.gradle`
after_script:
- |
reports_dir=build/reports/project/dependencies
while IFS= read -r -d '' src; do
dest="${src%%/$reports_dir/*}/gradle-html-dependency-report.js"
cp $src $dest
done < <(find . -type f -path "*/${reports_dir}/*.js" -not -path "*/${reports_dir}/js/*" -print0)
# Pass html report artifact to subsequent dependency scanning stage.
artifacts:
paths:
- "**/gradle-html-dependency-report.js"
The command above uses the report.gradle
file and can be supplied through --init-script
or its contents can be added to build.gradle
directly:
allprojects {
apply plugin: 'project-report'
}
The dependency report may indicate that dependencies for some configurations FAILED
to be resolved. In this case dependency scanning logs a warning but does not fail the job. If you prefer to have the pipeline fail if resolution failures are reported, add the following extra steps to the build
example above.
while IFS= read -r -d '' file; do
grep --quiet -E '"resolvable":\s*"FAILED' $file && echo "Dependency report has dependencies with FAILED resolution status" && exit 1
done < <(find . -type f -path "*/gradle-html-dependency-report.js -print0)
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.
Requirement: use at least version 3.7.0
of the maven-dependency-plugin.
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 org.apache.maven.plugins:maven-dependency-plugin:3.8.1: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"
pip
If your project provides a requirements.txt
lock file generated by the pip-compile command line tool, the Dependency Scanning analyzer can extract the list of components and the dependency graph information, which provides support for the dependency path feature.
Alternatively, your project can provide a pipdeptree.json
dependency graph export generated by the pipdeptree --json
command line utility.
The following example .gitlab-ci.yml
demonstrates how to enable the CI/CD component with dependency path support on a pip project. The build
stage outputs the dependency graph as a job artifact before dependency scanning runs.
stages:
- build
- test
include:
- component: $CI_SERVER_FQDN/components/dependency-scanning/main@0
build:
stage: build
image: "python:latest"
script:
- "pip install -r requirements.txt"
- "pip install pipdeptree"
- "pipdeptree --json > pipdeptree.json"
artifacts:
when: on_success
access: developer
paths: ["**/pipdeptree.json"]
Because of a known issue, pipdeptree
does not mark optional dependencies as dependencies of the parent package. As a result, Dependency Scanning marks them as direct dependencies of the project, instead of as transitive dependencies.
If your project provides only a Pipfile.lock
file, the Dependency Scanning analyzer can still extract the list of components. However, dependency path information is not available.
To benefit from improved feature coverage, you should provide a pipenv.graph.json
file generated by the pipenv graph
command.
The following example .gitlab-ci.yml
demonstrates how to enable the CI/CD component with dependency path support on a Pipenv project. The build
stage outputs the dependency graph as a job artifact before dependency scanning runs.
stages:
- build
- test
include:
- component: $CI_SERVER_FQDN/components/dependency-scanning/main@0
build:
stage: build
image: "python:3.12"
script:
- "pip install pipenv"
- "pipenv install"
- "pipenv graph --json-tree > pipenv.graph.json"
artifacts:
when: on_success
access: developer
paths: ["**/pipenv.graph.json"]
sbt
To enable the CI/CD component on an sbt project:
plugins.sbt
to use the sbt-dependency-graph plugin.The following example .gitlab-ci.yml
demonstrates how to enable the CI/CD component with dependency path support in an sbt project. The build
stage outputs the dependency graph as a job artifact before dependency scanning runs.
stages:
- build
- test
include:
- component: $CI_SERVER_FQDN/components/dependency-scanning/main@0
build:
stage: build
image: "sbtscala/scala-sbt:eclipse-temurin-17.0.13_11_1.10.7_3.6.3"
script:
- "sbt dependencyDot"
artifacts:
when: on_success
access: developer
paths: ["**/dependencies-compile.dot"]
Understanding the results
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 MaterialsThe 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:
gl-sbom-<package-type>-<package-manager>.cdx.json
.cyclonedx
reports.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.
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
Optimization
To optimize Dependency Scanning with SBOM according to your requirements you can:
To exclude files or directories from being scanned, use DS_EXCLUDED_PATHS
with a comma-separated list of patterns in your .gitlab-ci.yml
. This will prevent specified files and directories from being targeted by the scan.
To optimize the analyzer behavior you may set a max depth value through the DS_MAX_DEPTH
environment variable. A value of -1
scans all directories regardless of depth. The default is 2
.
After you are confident in the Dependency Scanning with SBOM results for a single project, you can extend its implementation to additional projects:
For the security analysis to be effective, the components listed in your SBOM report must have corresponding entries in the GitLab Advisory Database.
The GitLab SBOM Vulnerability Scanner can report Dependency Scanning vulnerabilities for components with the following PURL types:
cargo
composer
conan
gem
golang
maven
npm
nuget
pypi
How to customize the analyzer varies depending on the enablement solution.
Test all customization of GitLab analyzers in a merge request before merging these changes to the default branch. Failure to do so can give unexpected results, including a large number of false positives.
Customizing behavior with the CI/CD templateWhen using the latest
Dependency Scanning CI/CD template Dependency-Scanning.latest.gitlab-ci.yml
or Scan Execution Policies use CI/CD variables.
The following variables allow configuration of global dependency scanning settings.
CI/CD variables DescriptionDS_EXCLUDED_ANALYZERS
Specify the analyzers (by name) to exclude from Dependency Scanning. DS_EXCLUDED_PATHS
Exclude files and directories from the scan based on the paths. A comma-separated list of patterns. Patterns can be globs (see doublestar.Match
for supported patterns), or file or folder paths (for example, doc,spec
). Parent directories also match patterns. This is a pre-filter which is applied before the scan is executed. Default: "spec, test, tests, tmp"
. DS_MAX_DEPTH
Defines how many directory levels deep that the analyzer should search for supported files to scan. A value of -1
scans all directories regardless of depth. Default: 2
. DS_INCLUDE_DEV_DEPENDENCIES
When set to "false"
, development dependencies are not reported. Only projects using Composer, Conda, Gradle, Maven, npm, pnpm, Pipenv, Poetry, or uv are supported. Default: "true"
DS_PIPCOMPILE_REQUIREMENTS_FILE_NAME_PATTERN
Defines which requirement files to process using glob pattern matching (for example, requirements*.txt
or *-requirements.txt
). The pattern should match filenames only, not directory paths. See glob pattern documentation for syntax details. SECURE_ANALYZERS_PREFIX
Override the name of the Docker registry providing the official default images (proxy). DS_FF_LINK_COMPONENTS_TO_GIT_FILES
Link components in the dependency list to files committed to the repository rather than lockfiles and graph files generated dynamically in a CI/CD pipeline. This ensures all components are linked to a source file in the repository. Default: "false"
. Overriding dependency scanning jobs
To override a job definition declare a new job with the same name as the one to override. Place this new job after the template inclusion and specify any additional keys under it. For example, this configures the dependencies: []
attribute for the dependency-scanning job:
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
dependency-scanning:
dependencies: ["build"]
Customizing behavior with the CI/CD component
When using the Dependency Scanning CI/CD component, the analyzer can be customized by configuring the inputs.
How it scans an applicationThe dependency scanning using SBOM approach relies on two distinct phases:
This separation of concerns and the modularity of this architecture allows to better support customers through expansion of language support, a tighter integration and experience within the GitLab platform, and a shift towards industry standard report types.
Dependency detectionDependency scanning using SBOM requires the detected dependencies to be captured in a CycloneDX SBOM document. However, the modular aspect of this functionality allows you to select how this document is generated:
To activate dependency scanning using SBOM, the provided CycloneDX SBOM document must:
1.4
, 1.5
, or 1.6
. Online validator available on CycloneDX Web Tool.When using GitLab-provided analyzers, these requirements are met.
Security analysisAfter a compatible CycloneDX SBOM document is uploaded, GitLab automatically performs the security analysis with the GitLab SBOM Vulnerability Scanner. Each component is checked against the GitLab Advisory Database and scan results are processed in the following manners:
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: security findings are created, and can be seen in the security tab of the pipeline view and MR security widget. This functionality is behind a feature flag and tracked in Epic 14636.
Offline supportFor instances in an environment with limited, restricted, or intermittent access to external resources through the internet, you need to make some adjustments to run dependency scanning jobs successfully. For more information, see offline environments.
RequirementsTo run dependency scanning in an offline environment you must have:
docker
or kubernetes
executor.To use the dependency scanning analyzer:
Import the following default dependency scanning analyzer images from registry.gitlab.com
into your local Docker container registry:
registry.gitlab.com/security-products/dependency-scanning:v0
The process for importing Docker images into a local offline Docker registry depends on your network security policy. Consult your IT staff to find an accepted and approved process by which external resources can be imported or temporarily accessed. These scanners are periodically updated with new definitions, and you may want to download them regularly. In case your offline instance has access to the GitLab registry you can use the Security-Binaries template to download the latest dependency scanning analyzer image.
Configure GitLab CI/CD to use the local analyzers.
Set the value of the CI/CD variable SECURE_ANALYZERS_PREFIX
to your local Docker registry - in this example, docker-registry.example.com
.
include:
- template: Jobs/Dependency-Scanning.latest.gitlab-ci.yml
variables:
SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
Use security policies to enforce Dependency Scanning across multiple projects. The appropriate policy type depends on whether your projects have scannable artifacts committed to their repositories.
Scan execution policiesScan execution policies are supported for all projects that have scannable artifacts committed to their repositories. These artifacts include lockfiles, dependency graph files, and other files that can be directly analyzed to identify dependencies.
For projects with these artifacts, scan execution policies provide the fastest and most straightforward way to enforce Dependency Scanning.
Pipeline execution policiesFor projects that don’t have scannable artifacts committed to their repositories, you must use pipeline execution policies. These policies use a custom CI/CD job to generate scannable artifacts before invoking Dependency Scanning.
Pipeline execution policies:
For a Gradle project without a scannable artifact committed to the repository, a pipeline execution policy with an artifact generation step is required. This example uses the nebula
plugin.
In the dedicated security policies project create or update the main policy file (for example, policy.yml
):
pipeline_execution_policy:
- name: Enforce Gradle dependency scanning with SBOM
description: Generate dependency artifact and run Dependency Scanning.
enabled: true
pipeline_config_strategy: inject_policy
content:
include:
- project: $SECURITY_POLICIES_PROJECT
file: "dependency-scanning.yml"
Add dependency-scanning.yml
:
stages:
- build
- test
variables:
DS_ENFORCE_NEW_ANALYZER: "true"
include:
- template: Jobs/Dependency-Scanning.latest.gitlab-ci.yml
generate nebula lockfile:
image: openjdk:11-jdk
stage: build
script:
- |
cat << EOF > nebula.gradle
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:12.7.1'
}
}
allprojects {
apply plugin: nebula.plugin.dependencylock.DependencyLockPlugin
}
EOF
./gradlew --init-script nebula.gradle -PdependencyLock.includeTransitives=true -PdependencyLock.lockFile=dependencies.lock generateLock saveLock
./gradlew --init-script nebula.gradle -PdependencyLock.includeTransitives=false -PdependencyLock.lockFile=dependencies.direct.lock generateLock saveLock
after_script:
- find . -path '*/build/dependencies.lock' -print -delete
artifacts:
paths:
- '**/dependencies.lock'
- '**/dependencies.direct.lock'
This approach ensures that:
For more details on implementing pipeline execution policies for different build tools, refer to the language-specific instructions.
TroubleshootingWhen working with dependency scanning, you might encounter the following issues.
Warning:grep: command not found
The analyzer image contains minimal dependencies to decrease the image’s attack surface. As a result, utilities commonly found in other images, like grep
, are missing from the image. This may result in a warning like /usr/bin/bash: line 3: grep: command not found
to appear in the job log. This warning does not impact the results of the analyzer and can be ignored.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4