doc/user/application_security/secret_detection/pipeline/_index.md
{{< details >}}
{{< /details >}}
Pipeline secret detection scans files after they are committed to a Git repository and pushed to GitLab.
After you enable pipeline secret detection, scans run in a CI/CD job named secret_detection.
You can run scans and view pipeline secret detection JSON report artifacts in any GitLab tier.
With GitLab Ultimate, pipeline secret detection results are also processed so you can:
<i class="fa-youtube-play" aria-hidden="true"></i> For an interactive reading and how-to demo of this pipeline secret detection documentation see:
<i class="fa-youtube-play" aria-hidden="true"></i> For other interactive reading and how-to demos, see the Get Started With GitLab Application Security Playlist.
Different features are available in different GitLab tiers.
| Capability | In Free & Premium | In Ultimate |
|---|---|---|
| Customize analyzer behavior | {{< yes >}} | {{< yes >}} |
| Download output | {{< yes >}} | {{< yes >}} |
| See new findings in the merge request widget | {{< no >}} | {{< yes >}} |
| View identified secrets in the pipelines' Security tab | {{< no >}} | {{< yes >}} |
| Manage vulnerabilities | {{< no >}} | {{< yes >}} |
| Access the security dashboard | {{< no >}} | {{< yes >}} |
| Customize analyzer rulesets | {{< no >}} | {{< yes >}} |
| Enable security policies | {{< no >}} | {{< yes >}} |
To get started with pipeline secret detection, select a pilot project and enable the analyzer.
Prerequisites:
docker or
kubernetes executor.
If you use hosted runners for GitLab.com, this is enabled by default.
.gitlab-ci.yml file that includes the test stage.Enable the secret detection analyzer by using one of the following:
.gitlab-ci.yml file manually. Use this method if your CI/CD configuration is complex.If this is your first time running a secret detection scan on your project, you should run a historic scan immediately after you enable the analyzer.
After you enable pipeline secret detection, you can customize the analyzer settings.
.gitlab-ci.yml file manuallyThis method requires you to manually edit an existing .gitlab-ci.yml file.
In the top bar, select Search or go to and find your project.
Select Build > Pipeline editor.
Copy and paste the following to the bottom of the .gitlab-ci.yml file:
include:
- template: Jobs/Secret-Detection.gitlab-ci.yml
Select the Validate tab, then select Validate pipeline. The message Simulation completed successfully indicates the file is valid.
Select the Edit tab.
Optional. In the Commit message text box, customize the commit message.
In the Branch text box, enter the name of the default branch.
Select Commit changes.
Pipelines now include a pipeline secret detection job. Consider running a historic scan after you enable the analyzer.
This method automatically prepares a merge request to add a .gitlab-ci.yml file that includes the pipeline secret detection template. Merge the merge request to enable pipeline secret detection.
To enable pipeline secret detection:
Pipelines now include a pipeline secret detection job.
Pipeline secret detection is optimized to balance coverage and run time. Only the current state of the repository and future commits are scanned for secrets. To identify secrets already present in the repository's history, run a historic scan once after enabling pipeline secret detection. Scan results are available only after the pipeline is completed.
Exactly what is scanned for secrets depends on the type of pipeline, and whether any additional configuration is set.
By default, when you run a pipeline:
To override the default behavior, use the available CI/CD variables.
By default, when GitLab first clones a repository, it fetches only the most recent commits (a "shallow clone"). When additional commits are needed beyond this initial clone, the analyzer automatically fetches them using optimized strategies:
--since or --max-count, the analyzer fetches only the required commits.--unshallow option.If the analyzer cannot fetch the required commits, it falls back to scanning available data:
These fallbacks ensure your pipeline completes successfully, even in restricted environments.
The runner's GIT_DEPTH controls how many commits are initially cloned. Pipeline secret detection automatically fetches additional commits when needed, so you typically don't need to adjust this setting.
If you experience persistent issues with missing commits in restricted network environments, see the troubleshooting for workarounds.
By default, pipeline secret detection scans only the current state of the Git repository. Any secrets contained in the repository's history are not detected. Run a historic scan to check for secrets from all commits and branches in the Git repository.
You should run a historic scan only once, after enabling pipeline secret detection. Historic scans can take a long time, especially for larger repositories with lengthy Git histories. After completing an initial historic scan, use only standard pipeline secret detection as part of your pipeline.
If you enable pipeline secret detection with a scan execution policy, by default the first scheduled scan is a historic scan.
To run a historic scan:
SECRET_DETECTION_HISTORIC_SCAN.true.{{< details >}}
{{< /details >}}
{{< history >}}
{{< /history >}}
Secret detection uses an advanced vulnerability tracking algorithm to prevent duplicate findings and vulnerabilities from being created when a file is refactored or moved.
A new finding is not created when:
Duplicate vulnerability tracking works on a per-file basis. If the same secret appears in two different files, two findings are created.
For more information, see the confidential project https://gitlab.com/gitlab-org/security-products/post-analyzers/tracking-calculator.
This project is available only to GitLab team members.
Duplicate vulnerability tracking doesn't support workflows where:
The existing finding lacks a tracking signature and doesn't share the same location as the new finding.
Certain secrets are detected by searching for their prefixes instead of the entire secret value. For these secret types, all the detections of the same type and in the same file are reported as a single finding.
For example, an SSH private key is detected by its prefix -----BEGIN OPENSSH PRIVATE KEY-----. If there are multiple SSH private keys in the same file,
pipeline secret detection creates only one finding.
When running a historic scan or enabling pipeline secret detection on existing commits, if a secret is introduced in one commit and then modified in a later commit during the same scan, only the most recent secret value appears in the vulnerability report.
Pipeline secret detection scans the repository's content for specific patterns. Each pattern matches a specific type of secret and is specified in a rule by using a TOML syntax. GitLab maintains the default set of rules.
With GitLab Ultimate you can extend these rules to suit your needs. For example, while personal access tokens that use a custom prefix are not detected by default, you can customize the rules to identify these tokens. For details, see Customize analyzer rulesets.
To confirm which secrets are detected by pipeline secret detection, see Detected secrets. To provide reliable, high-confidence results, pipeline secret detection only looks for passwords or other unstructured secrets in specific contexts like URLs.
When a secret is detected a vulnerability is created for it. The vulnerability remains as "Still detected" even if the secret is removed from the scanned file and pipeline secret detection has been run again. This is because the leaked secret continues to be a security risk until it has been revoked. Removed secrets also persist in the Git history. To remove a secret from the Git repository's history, see Redact text from repository.
To improve performance, pipeline secret detection automatically excludes certain file types and directories with a low likelihood of containing secrets.
The following items are excluded:
| Category | Excluded items |
|---|---|
| Configuration files | Files: gitleaks.toml, verification-metadata.xml, Database.refactorlog, .editorconfig, .gitattributes |
| Media and binary files | Extensions: .bmp, .gif, .svg, .jpg/.jpeg, .png, .tiff/.tif, .webp, .ico, .heic |
Fonts: .eot, .otf, .ttf, .woff, .woff2 | |
Documents: .doc/.docx, .xls/.xlsx, .ppt/.pptx, .pdf | |
Audio/video: .mp3, .mp4, .wav, .flac, .aac, .ogg, .avi, .mkv, .mov, .wmv, .flv, .webm | |
Archives: .zip, .rar, .7z, .tar, .gz, .bz2, .xz, .dmg, .iso | |
Executables: .exe, .gltf | |
| Visual Studio files | Extensions: .socket, .vsidx, .suo, .wsuo, .dll, .pdb |
| Package lock files | Files: deno.lock, npm-shrinkwrap.json, package-lock.json, pnpm-lock.yaml, yarn.lock, Pipfile.lock, poetry.lock, gradle.lockfile, Cargo.lock, composer.lock |
| Go language files | Extensions: go.mod, go.sum, go.work, go.work.sum |
Directories: vendor/ (only for Go modules from github.com, golang.org, google.golang.org, gopkg.in, istio.io, k8s.io, sigs.k8s.io) | |
Files: vendor/modules.txt | |
| Ruby files | Directories: .bundle/, gems/, specifications/ |
Extensions: .gem files in gems/ directory, .gemspec files in specifications/ directory | |
| Build tool wrappers | Files: gradlew, gradlew.bat, mvnw, mvnw.cmd |
Directories: .mvn/wrapper/ | |
Specific: MavenWrapperDownloader.java in Maven wrapper directory | |
| Dependency directories | Directories: node_modules/, bower_components/, packages/ |
| Build output directories | Directories: target/, build/, bin/, obj/ |
| Vendor directories | Directories: vendor/bundle/, vendor/ruby/, vendor/composer/ |
| Python cache files | Extensions: .pyc, .pyo |
Directories: __pycache__/ | |
| Python tool caches | Directories: .pytest_cache/, .mypy_cache/, .tox/ |
| Python virtual environments | Directories: venv/, virtualenv/, .venv/, env/ |
| Python installation directories | Directories: lib/python[version]/, lib64/python[version]/, python[version]/lib/, python[version]/Lib/ |
| Python package metadata | Package names ending with version and .dist-info |
| JavaScript libraries | Files: angular*.js, bootstrap*.js, jquery*.js, jquery-ui*.js, plotly*.js, swagger-ui*.js |
Source Maps: Corresponding .js.map files | |
| Minified/bundled assets | Extensions: .min.js, .min.css, .bundle.js, .bundle.css, .map (source map files) |
| Compiled files | Extensions: .class, .o, .obj, .jar, .war (Web archive), .ear |
| Cache directories | Directories: .cache/, .coverage/, .pytest_cache/, .mypy_cache/, .tox/ |
| Generated documentation | Directories: htmlcov/, coverage/, _build/, _site/, docs/_build/ |
| Version control and IDEs | Directories: .git/, .svn/, .hg/, .bzr/ (version control), .vscode/, .idea/, .eclipse/, .vs/ (IDEs) |
| Operating system files | Files: .DS_Store, Thumbs.db |
Pipeline secret detection outputs the file gl-secret-detection-report.json as a job artifact. The file contains detected secrets. You can download the file for processing outside GitLab.
For more information, see the report file schema and the example report file.
{{< details >}}
{{< /details >}}
Job results are also reported on the:
Pipeline secret detection provides detailed information about potential secrets found in your repository. Each secret includes the type of secret leaked and remediation guidelines.
When reviewing results:
Detections by pipeline secret detection often fall into one of three categories:
When a secret is detected, you should rotate it immediately. GitLab attempts to automatically revoke some types of leaked secrets. For those that are not automatically revoked, you must do so manually.
Purging a secret from the repository's history does not fully address the leak. The original secret remains in any existing forks or clones of the repository.
For instructions on how to respond to a leaked secret, select the vulnerability in the vulnerability report.
Before deploying pipeline secret detection across your organization, optimize the configuration to reduce false positives and improve accuracy for your specific environment.
False positives can create alert fatigue and reduce trust in the tool. Consider using custom ruleset configuration (Ultimate only):
To optimize performance in large repositories or organizations with many projects, review your:
Before applying optimizations organization-wide:
You should implement pipeline secret detection incrementally. Start with a small-scale pilot to understand the tool's behavior before rolling out the feature across your organization.
Follow these guidelines when you roll out pipeline secret detection:
{{< history >}}
{{< /history >}}
The default scanner images are built off a base Alpine image for size and maintainability. GitLab offers Red Hat UBI versions of the images that are FIPS-enabled.
To use the FIPS-enabled images, either:
SECRET_DETECTION_IMAGE_SUFFIX CI/CD variable to -fips.-fips extension to the default image name.For example:
variables:
SECRET_DETECTION_IMAGE_SUFFIX: '-fips'
include:
- template: Jobs/Secret-Detection.gitlab-ci.yml
Debug-level logging can help when troubleshooting. For details, see debug-level logging.
gl-secret-detection-report.json: no matching filesFor information on this, see the general application security troubleshooting section.
Couldn't run the gitleaks command: exit status 2This error indicates the analyzer cannot access required commits. While the analyzer automatically fetches missing commits in most cases, issues can occur in restricted environments.
To diagnose the issue, enable debug-level logging and look for:
ERRO[2020-11-18T18:05:52Z] object not found
[ERRO] [secrets] [2020-11-18T18:05:52Z] ▶ Couldn't run the gitleaks command: exit status 2
[ERRO] [secrets] [2020-11-18T18:05:52Z] ▶ Gitleaks analysis failed: exit status 2
To resolve this issue:
For most cases, no action is required. Let the analyzer handle fetching automatically.
For restricted networks, increase the initial clone depth:
secret_detection:
variables:
GIT_DEPTH: 100 # or 0 to clone everything
For large repositories, limit the scan scope:
secret_detection:
variables:
SECRET_DETECTION_LOG_OPTIONS: "--max-count=50"
ERR fatal: ambiguous argumentPipeline secret detection can fail with the message ERR fatal: ambiguous argument error if your
repository's default branch is unrelated to the branch the job was triggered for. See issue
!352014 for more details.
To resolve the issue, make sure to correctly set your default branch
on your repository. You should set it to a branch that has related history with the branch you run
the secret-detection job on.
exec /bin/sh: exec format error message in job logThe GitLab pipeline secret detection analyzer only supports running on the amd64 CPU architecture.
This message indicates that the job is being run on a different architecture, such as arm.
fatal: detected dubious ownership in repository at '/builds/<project dir>'Secret detection might fail with an exit status of 128. This can be caused by a change to the user on the Docker image.
For example:
$ /analyzer run
[INFO] [secrets] [2024-06-06T07:28:13Z] ▶ GitLab secrets analyzer v6.0.1
[INFO] [secrets] [2024-06-06T07:28:13Z] ▶ Detecting project
[INFO] [secrets] [2024-06-06T07:28:13Z] ▶ Analyzer will attempt to analyze all projects in the repository
[INFO] [secrets] [2024-06-06T07:28:13Z] ▶ Loading ruleset for /builds....
[WARN] [secrets] [2024-06-06T07:28:13Z] ▶ /builds/....secret-detection-ruleset.toml not found, ruleset support will be disabled.
[INFO] [secrets] [2024-06-06T07:28:13Z] ▶ Running analyzer
[FATA] [secrets] [2024-06-06T07:28:13Z] ▶ get commit count: exit status 128
To work around this issue, add a before_script with the following:
before_script:
- git config --global --add safe.directory "$CI_PROJECT_DIR"
For more information about this issue, see issue 465974.
GIT_DEPTH doesn't change what gets scannedThis is expected behavior. GIT_DEPTH is a runner variable for the initial clone. It doesn't change analyzer behavior.
The secret detection analyzer decides what to scan based on:
SECRET_DETECTION_LOG_OPTIONS, SECRET_DETECTION_HISTORIC_SCAN)For example, to scan only 30 commits:
secret_detection:
variables:
# Scan the last 30 commits
SECRET_DETECTION_LOG_OPTIONS: "--max-count=30"
To scan only commits from the last two weeks:
secret_detection:
variables:
# Scan commits made in the last two weeks
SECRET_DETECTION_LOG_OPTIONS: "--since=2.weeks"
To scan only commits from HEAD~10 to HEAD:
secret_detection:
variables:
# Scan commits from HEAD~10 to HEAD
SECRET_DETECTION_LOG_OPTIONS: "HEAD~10..HEAD"
For a full list of options, see the Git log options documentation.
After a force push, you might see:
Failed to retrieve all the commits from the last Git push event due to a force push
This is expected behavior. The scan continues using the current repository state.
You might see the message:
Added project directory to Git safe.directory configuration
This indicates typical security configuration in containerized environments. No action is required.