How to enable secret detection using GitLab Open Source Secret Analyzer
Here in this article we will try to setup GitLab server along with GitLab runner and will try to scan a java spring based project for secret detection using GitLab Open Source secret analyzer.
Test Environment
- GitLab Server: Ubuntu 24.04
- GitLab Runner: Ubuntu 24.04
Here in this demo, ubser1.stack.com will act as GitLab server and ubser2.stack.com will act as GitLab Runner. Both of these server are installed with Ubuntu OS 24.04.
GitLab Secret Detection
Secrets are entities such as API keys, Access tokens or Private keys which are usually used to authenticate with thirdparty services or platforms. As a best pratice you should avoid keeping your secrets within the project repository as these could have adverse effect if leaked into attackers hand.
Secret detection is a process through which the source code repositories are scanned to identify any such detected secrets. GitLab secret detection helps to scan the source code and provide a report on all the identified secrets. The free version of GitLab provides Pipeline secret detection by defining secret detection scan stage within the CICD pipeline.
Also GitLab provides Client-side secret detection thats scans descriptions and comments in both issues and merge requests for secrets before they’re saved to GitLab.
If you are interested in watching the video. Here is the YouTube video on the same step by step procedure outlined below.
Procedure
Step1: Ensure GitLab server installed and running
Follow “How to setup Gitlab EE on Ubuntu OS” to setup your GitLab EE server using Linux package. Also this is continuation to previous article on “How to enable Static Code analysis using GitLab Open Source Analyzer“.
Step2: Ensure SSH service enabled
Ensure that you have Ubuntu OS 24.04 installed and running on your system or virtual machine. Make sure to update the packages to the latest version and install the OpenSSH server to enable SSH access.
ubadmin@ubser1:~$ sudo apt-get update
ubadmin@ubser1:~$ sudo apt-get upgrade
ubadmin@ubser1:~$ sudo apt-get install openssh-server
ubadmin@ubser1:~$ sudo systemctl start ssh.service
ubadmin@ubser1:~$ sudo systemctl enable ssh.service
ubadmin@ubser2:~$ sudo apt-get update
ubadmin@ubser2:~$ sudo apt-get upgrade
ubadmin@ubser2:~$ sudo apt-get install openssh-server
ubadmin@ubser2:~$ sudo systemctl start ssh.service
ubadmin@ubser2:~$ sudo systemctl enable ssh.service
Step3: Add GitLab Runner Respository
GitLab Runner is an application that manages the execution on CICD pipeline jobs. GitLab Runner can run as a single binary and has no language-specific requirements.
It is recommended to install GitLab runner on a separate machine from the machine that hosts the GitLab instance. Here we will install GitLab runner from the Linux deb package manager repository.
ubadmin@ubser2:~$ sudo apt-get install curl
ubadmin@ubser2:~$ curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
Detected operating system as Ubuntu/noble.
Checking for curl...
Detected curl...
Checking for gpg...
Detected gpg...
Detected apt version as 2.8.3
Running apt-get update... done.
Installing apt-transport-https... done.
Installing /etc/apt/sources.list.d/runner_gitlab-runner.list...done.
Importing packagecloud gpg key... Packagecloud gpg key imported to /etc/apt/keyrings/runner_gitlab-runner-archive-keyring.gpg
done.
Running apt-get update... done.
The repository is setup! You can now install packages.
Step4: Install GitLab Runner
Now that the gitlab-runner repository has been added, we can install the gitlab-runner deb package as shown below.
ubadmin@ubser2:~$ sudo apt install gitlab-runner
Step5: Install Docker Engine
Here we are going to install the docker engine on the gitlab runner server which will be executing our jobs within isolated docker conatainer environment.
Add GPG Signing keyring file
ubadmin@ubser2:~$ sudo apt update
ubadmin@ubser2:~$ sudo apt install ca-certificates curl
ubadmin@ubser2:~$ sudo install -m 0755 -d /etc/apt/keyrings
ubadmin@ubser2:~$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
ubadmin@ubser2:~$ sudo chmod a+r /etc/apt/keyrings/docker.asc
Add Docker Engine repository
ubadmin@ubser2:~$ sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
Install Docker Engine
ubadmin@ubser2:~$ sudo apt-get update
ubadmin@ubser2:~$ sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
ubadmin@ubser2:~$ sudo systemctl status docker
Post Installation
ubadmin@ubser2:~$ sudo groupadd docker
ubadmin@ubser2:~$ sudo usermod -aG docker $USER
Validate Docker Installation with Non root user
ubadmin@ubser2:~$ docker run hello-world
Step6: Create an Instance Runner with Runner Authentication Token
Instance runners are available to every project in a GitLab instance.

Once you create an instance runner, it will provide the instruction to register the runner with runner authentication token.

Here is the command for runner registration with token.
gitlab-runner register --url http://ubser1.stack.com --token glrt-W-WLZVeWumiRa1xCm6nIwG86MQp0OjEKdToxCw.01.121mjc24e
Step7: Register GitLab Runner with Docker executor
Let’s execute the command to register our runner as shown below. This will be an interactive process in which it will ask for executor and default docker image to use. Here we are setting them to “docker” and “ruby:3.3”.
ubadmin@ubser2:~$ gitlab-runner register --url http://ubser1.stack.com --token glrt-W-WLZVeWumiRa1xCm6nIwG86MQp0OjEKdToxCw.01.121mjc24e
Runtime platform arch=amd64 os=linux pid=5482 revision=df85dadf version=18.6.6
WARNING: Running in user-mode.
WARNING: The user-mode requires you to manually start builds processing:
WARNING: $ gitlab-runner run
WARNING: Use sudo for system-mode:
WARNING: $ sudo gitlab-runner...
Created missing unique system ID system_id=s_e1a1d829706d
Enter the GitLab instance URL (for example, https://gitlab.com/):
[http://ubser1.stack.com]:
Verifying runner... is valid correlation_id=01KCKW1XG5YHQV6DSJY3FZAJHY runner=W-WLZVeWu
Enter a name for the runner. This is stored only in the local config.toml file:
[ubser2.stack.com]:
Enter an executor: custom, parallels, docker, kubernetes, docker-autoscaler, instance, shell, ssh, virtualbox, docker-windows, docker+machine:
docker
Enter the default Docker image (for example, ruby:3.3):
Enter the default Docker image (for example, ruby:3.3):
ruby:3.3
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
Configuration (with the authentication token) was saved in "/home/ubadmin/.gitlab-runner/config.toml"
The user-mode requires you to manually start builds processing. So we need to run the following to ensure our gitlab runner is able to process the pipeline jobs.
ubadmin@ubser2:~$ gitlab-runner run
Step8: Create a GitLab project
For this demo lets create a gitlab project using a sample “Spring” template as shown below.

Now let’s edit the .gitlab-ci.yml file using the edit with pipeline editor on the portal itself and update it as shown below. We have updated two thing in this yaml definition file.
- Updated the template for secret detection using the Open Source gitleaks secret detection image with template “Jobs/Secret-Detection.gitlab-ci.yml”
- Updated each job with a tag name “sastdemo” so that it can be picked up by the gitlab runner with tag “sastdemo”
# This file is a template, and might need editing before it works on your project.
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
# This is a sample GitLab CI/CD configuration file that should run without any modifications.
# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
# it uses echo commands to simulate the pipeline execution.
#
# A pipeline is composed of independent jobs that run scripts, grouped into stages.
# Stages run in sequential order, but jobs within stages run in parallel.
#
# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages
stages: # List of stages for jobs, and their order of execution
- build
- test
- deploy
include:
#- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Secret-Detection.gitlab-ci.yml
secret_detection:
variables:
SECRETS_ANALYZER_VERSION: "4.5"
SECRET_DETECTION_HISTORIC_SCAN: "true"
tags:
- sastdemo
# Override the default SAST job configuration
sast:
tags:
- sastdemo # Replace 'your-runner-tag' with your actual runner tag
build-job: # This job runs in the build stage, which runs first.
stage: build
script:
- echo "Compiling the code..."
- echo "Compile complete."
tags:
- sastdemo
unit-test-job: # This job runs in the test stage.
stage: test # It only starts when the job in the build stage completes successfully.
script:
- echo "Running unit tests... This will take about 60 seconds."
- sleep 60
- echo "Code coverage is 90%"
tags:
- sastdemo
lint-test-job: # This job also runs in the test stage.
stage: test # It can run at the same time as unit-test-job (in parallel).
script:
- echo "Linting code... This will take about 10 seconds."
- sleep 10
- echo "No lint issues found."
tags:
- sastdemo
deploy-job: # This job runs in the deploy stage.
#environment: production
stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
script:
- echo "Deploying application..."
- echo "Application successfully deployed."
tags:
- sastdemo
Also let’s update “DemoApplication.java” as shown below to introduce a SAST and GitLab Secret token vulnerability.
package com.example.demo;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
public class DemoApplication {
//test
@GetMapping("/")
public String home() {
String some_test_token = "glpat-JUST20LETTERSANDNUMB"
return "Spring is here!";
}
@GetMapping("/user")
public String getUser(@RequestParam(value = "id") String id) {
URL url = new URL("http://example.com/api/user/" + id); // Noncompliant
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Step9: Validate Pipeline execution status
Now let’s validate the status of the pipeline and verify each job has been executed successfully.

Step10: Download Secrets Scan report
Now in your pipeline you can see the “download artifacts” option to download you SAST and Secret Scan report in JSON format to analyze further.

admin@fedser:Downloads$ cat gl-secret-detection-report.json | jq
{
"version": "14.0.4",
"vulnerabilities": [
{
"id": "1572d1e1e53f0551deb03c0925957f56e02a779b89900f928c43e570a92bef29",
"category": "secret_detection",
"name": "GitLab Personal Access Token",
"message": "GitLab Personal Access Token detected; please remove and revoke it if this is a leak.",
"description": "GitLab Personal Access Token secret has been found in commit 009449a2.",
"cve": "src/main/java/com/example/demo/DemoApplication.java:a94d1729c3aef04eaf917cbcf257787e9441fc9683761dff84c22441b7b04c4c:gitlab_personal_access_token",
"severity": "Critical",
"confidence": "Unknown",
"raw_source_code_extract": "glpat-JUST20LETTERSANDNUMB",
"scanner": {
"id": "gitleaks",
"name": "Gitleaks"
},
"location": {
"file": "src/main/java/com/example/demo/DemoApplication.java",
"commit": {
"author": "gitlabuser",
"date": "2025-12-20T15:36:42Z",
"message": "Edit DemoApplication.java",
"sha": "009449a2495ace33cfbc62dc0b1866b765ba95a8"
},
"start_line": 15
},
"identifiers": [
{
"type": "gitleaks_rule_id",
"name": "Gitleaks rule ID gitlab_personal_access_token",
"value": "gitlab_personal_access_token"
}
]
}
],
"dependency_files": [],
"scan": {
"analyzer": {
"id": "secrets",
"name": "secrets",
"url": "https://gitlab.com/gitlab-org/security-products/analyzers/secrets",
"vendor": {
"name": "GitLab"
},
"version": "4.5.19"
},
"scanner": {
"id": "gitleaks",
"name": "Gitleaks",
"url": "https://github.com/zricethezav/gitleaks",
"vendor": {
"name": "GitLab"
},
"version": "8.16.2"
},
"type": "secret_detection",
"start_time": "2025-12-20T15:37:35",
"end_time": "2025-12-20T15:37:35",
"status": "success"
}
}
Step11: List Secrets detected
Here is sample command which can be used to parse the JSON file and list all the secrets with their severity, name and file location as shown below.
admin@fedser:Downloads$ cat gl-secret-detection-report.json | jq -r ' .vulnerabilities[] | [ .severity, .name, .location.file ] | @csv' | sort -u
"Critical","GitLab Personal Access Token","src/main/java/com/example/demo/DemoApplication.java"
Hope you enjoyed reading this article. Thank you..
Leave a Reply
You must be logged in to post a comment.