Automated DevSecOps: Implementing SAST & Secret Detection in GitLab CI/CD
In modern software development, security cannot be an afterthought audited right before a quarterly release.
A single leaked API key committed to a public repository can compromise cloud infrastructure in seconds. Similarly, subtle buffer overflows, SQL injection vulnerabilities, or insecure cryptographic primitives introduced in routine pull requests can linger unnoticed for months.
One of GitLab’s greatest superpowers is its built-in DevSecOps suite. Rather than requiring expensive third-party SaaS security subscriptions, GitLab provides battle-tested security scanners directly inside your .gitlab-ci.yml pipeline.
In this practical guide, I will show you how to configure Secret Detection, Static Application Security Testing (SAST), and Dependency Scanning in GitLab CI/CD to block security regressions before they hit production.
1. The DevSecOps Pipeline Flow
Instead of relying solely on post-deployment penetration testing, security checks run in parallel with standard unit tests on every commit:
+-------------------------------------------------------------+
| git push origin |
+-------------------------------------------------------------+
|
v
+-------------------------------------------------------------+
| GitLab CI/CD Pipeline |
+-------------------------------------------------------------+
| | |
v v v
+------------------+ +-------------------+ +-------------------+
| Secret Detection | | SAST Scanner | | Dependency Check |
| (Gitleaks Engine)| | (Semgrep / Flaw) | | (Gemnasium Engine)|
+------------------+ +-------------------+ +-------------------+
\ | /
-------------------------------------------------
|
v
+-------------------------------------------------------------+
| Security Tab in Merge Request Dashboard |
| - Blocks merge if High / Critical vulnerabilities |
| - Provides line-level remediation guidance |
+-------------------------------------------------------------+
2. Setting Up Native Security Templates in .gitlab-ci.yml
GitLab provides officially maintained CI/CD security templates. You don't need to write custom docker scripts or manage security scanner binaries.
Here is a production-ready .gitlab-ci.yml that includes Secret Detection and SAST:
stages:
- test
- security
include:
# 1. Official Secret Detection template
- template: Security/Secret-Detection.gitlab-ci.yml
# 2. Official SAST template (Multi-language code scanning)
- template: Security/SAST.gitlab-ci.yml
# 3. Dependency Scanning template
- template: Security/Dependency-Scanning.gitlab-ci.yml
# Customize Secret Detection behavior
secret_detection:
stage: security
variables:
SECRET_DETECTION_HISTORIC_SCAN: "false" # Set true on first run to scan git history
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
# Customize SAST behavior
sast:
stage: security
variables:
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
SEARCH_MAX_DEPTH: "4"
artifacts:
reports:
sast: gl-sast-report.json
3. How Secret Detection Catches Leaked Credentials
GitLab’s Secret Detection uses rules derived from Gitleaks to inspect both committed files and git commit history for over 100 known credential patterns:
- AWS Access Keys (
AKIA...) - GitLab Personal Access Tokens (
glpat-...) - GitHub Tokens (
ghp_...) - Private SSH / RSA / ED25519 Keys
- Slack Webhook URLs
Simulating a Regressed Commit:
If a developer accidentally commits:
# config.py
DATABASE_URL = "postgres://admin:supersecretpassword@10.0.0.5:5432/production"
GITLAB_PAT = "glpat-xxxxxxxxxxxxxxxxxxxx"
The secret_detection job immediately fails with:
[CRITICAL] GitLab Personal Access Token detected
File: config.py
Line: 3
Rule ID: gitlab_personal_access_token
Commit: d8b2c4e (chore: added db config)
The Merge Request is blocked, preventing the secret from ever merging into the protected main branch.
4. Static Application Security Testing (SAST) in Action
While secret detection looks for tokens, SAST analyzes your actual source code AST (Abstract Syntax Tree) using specialized rule engines like Semgrep, Brakeman (Ruby), and Flawfinder (C/C++).
Common Vulnerabilities Caught Automatically:
-
SQL Injections: Catching unescaped string interpolation in database queries (
SELECT * FROM users WHERE id = #{params[:id]}). -
Buffer Overflows: Flagging unsafe functions like
strcpyorgetsin C/C++ code and recommendingstrncpy_s. -
Insecure Deserialization: Identifying unsafe
pickle.loadsin Python oreval()in JavaScript. - Weak Cryptography: Flagging outdated MD5 or SHA-1 hashes used for password hashing.
5. Integrating with GitLab Duo for Automated Remediation
If you use GitLab Duo, security findings can be automatically remediated with generative AI!
When a vulnerability is flagged in your Merge Request:
- Click on the finding in the Security tab.
- Click "Explain Vulnerability with GitLab Duo".
- Duo analyzes the code context and explains why the pattern is unsafe.
- Click "Create Merge Request with Resolution" to automatically apply the secure refactored code.
6. Best Practices for High-Performance DevSecOps
-
Keep Scans Incremental: In Merge Requests, scan only the changed files (
SECRET_DETECTION_HISTORIC_SCAN: "false"), and run full historical scans on a weekly schedule. -
Fail Fast on Criticals: Configure Merge Request Approval Rules to require approval from a security lead if any
HighorCriticalseverity vulnerabilities are detected. -
Exclude Mock Data: Exclude test fixtures and dummy mock tokens using
SAST_EXCLUDED_PATHSto prevent false alarms.
Resources & Links
- GitLab Profile: gitlab.com/hrlpavan
- GitLab Contributor Profile: contributors.gitlab.com/users/hrlpavan
- GitHub: @hrlpavan
What security scanners do you run in your CI pipelines? Share your DevSecOps configuration tips in the comments below!
Top comments (0)