version v7.2.
For up-to-date documentation, see the
latest version.
Secret Detection
4 minute read
Secret Detection scans your code for sensitive information—such as API keys, passwords, tokens, and certificates—to prevent accidental exposure in version control systems.
Committed secrets create immediate security risks: they become visible to anyone with repository access, persist in Git history even after deletion, and can be exploited by automated scanning bots.
Always treat exposed secrets as compromised, even in private repositories. Team members, compromised accounts, or future visibility changes can expose them.
Defense Layers
Secret detection operates at different stages of your development workflow. Use multiple layers for comprehensive protection.
| Tool | Stage | Description |
|---|---|---|
| SonarQube for IDE | IDE | Scans files locally as you type |
| JFrog IDE Extension | IDE | Scans files locally as you type |
| GitLab Secret Push Protection | Server-side push | Rejects pushes containing secrets before they land |
| GitLab Secret Detection | Pipeline | Scans code changes before merging |
| SonarQube | Pipeline | Additional pipeline validation with different rules |
| JFrog Xray | Artifact | Scans binaries, images and dependencies |
Minimum Configuration (Recommended for All Projects)
- GitLab Secret Push Protection: rejects pushes containing secrets before they enter your repository. This is your primary defense layer.
- GitLab Secret Detection: pipeline scanning for additional validation after code has been pushed. Catches secrets that might have bypassed push protection.
Enhanced Protection (Recommended)
Add IDE-level detection for earlier feedback, preventing secrets from ever being committed:
- SonarQube for IDE or JFrog IDE Extension: real-time feedback as you code.
Comprehensive Protection
For high-security projects, add:
- SonarQube (if used for code quality): an additional pipeline validation layer using a different ruleset than GitLab’s native detection.
- JFrog Xray (if publishing artifacts): scans compiled binaries, container images, and third-party dependencies for embedded secrets.
Start with GitLab’s native protections, then add IDE extensions for developers. Additional tools provide defense-in-depth but aren’t required for basic security.
Secret Leak Contingency
When a secret is accidentally leaked, it poses a serious security risk. The following steps outline how to respond quickly.
Treat the Secret as Compromised
- Assume anyone with access to the repository (including forks and clones) can retrieve the secret, even if it is later “deleted” via a commit.
- The secret may have already been seen, copied, or indexed outside your organization.
Revoke or Rotate the Secret Immediately
This is the most important step.
- Change the affected credentials at the source (reset passwords, generate new API tokens …).
- Remove or disable the compromised secret so it cannot be used.
- Deploy the replacement credentials securely.
Always revoke, even if the secret never reached a remote repository. It may exist in local clones, backups, or logs.
Notify Relevant Stakeholders
- Inform your internal security contact (e.g., PSO or Security Guardian).
- If external systems or collaborators are impacted, notify those third parties as appropriate.
Check Access Logs for Abuse
- Review relevant access logs for suspicious or unauthorized activity using the compromised secret.
- Document findings and preserve evidence where appropriate.
Remove the Secret from Git History
The revocation protects you, not the history cleanup. If properly revoked, old commits cannot be exploited even if they remain in history.
Even after rotating the secret, it’s best practice to remove the leaked secret from all Git history. The approach depends on the situation:
- Secret in your latest commit: amend your last commit with
git commit --amend. - Secret in identifiable older commits: use a Git rebase to rewrite the commits containing the secret.
- Secret hard to locate or spread across many commits: use Git filter-repo to search and replace across the entire repository history.
In all cases, if the commits were already pushed, a force push is required afterwards.
Removing a secret from your branch does not delete the orphaned commit object from the
repository.
Locally, run git reflog expire --expire=now --all && git gc --prune=now.
On GitLab, orphaned commits remain accessible by hash until the next garbage collection
(default: daily).
For sensitive secrets, request your GitLab administrator to trigger
manual GC immediately.
Example with git filter-repo — replacing a secret string across all history:
# Create a replacements file
echo "my_leaked_secret==>REMOVED" > replacements.txt
# Rewrite history
git filter-repo --replace-text replacements.txt
For more information, check following articles:
Verify and Prevent Recurrence
- Check for similar secrets elsewhere in the codebase
- If secret detection was already in place, investigate why the leak was not caught
- Inform the PSO (Product Security Officer) to determine if further actions are needed
Next Steps
Configure secret detection in your projects:
- Enable GitLab Secret Push Protection (recommended first step)
- Enable GitLab Secret Detection in pipelines