Secret scanning
A password or API token committed to Git stays in the history long after someone deletes the line, so you want to catch it before it merges. This page is for developers and leads on a project built from Vortex. It shows how to run the secret scan locally, scan the Git history, ignore a false positive, and read the findings in continuous integration (CI).
Gitleaks catches those secrets: it scans the code for hardcoded secrets like passwords, API keys, and tokens, and fails the security audit when it finds one.
Usage
Vortex doesn't install Gitleaks locally, so install it on your system first; see the Gitleaks installation instructions. Then run the scan from the project root:
gitleaks dir .
Gitleaks reads .gitleaks.toml from the directory it scans, which is why
the command runs from the project root. It prints only the number of
findings by default; add -v to see each finding. On a clean codebase, the
scan ends with no leaks found.
gitleaks dir scans the files on disk, the same as CI, and doesn't look at
the Git history. To scan the commits too, see
Scanning the Git history.
Configuration
Global configuration lives in the
.gitleaks.toml
file at the repository root; see the Gitleaks configuration
documentation. The
file extends Gitleaks' default rule set and allowlists the following paths,
which hold third-party, generated, or local-only files:
.artifacts/.data/.git/.logs/node_modules/vendor/web/core/web/libraries/web/modules/contrib/web/sites/default/files/web/themes/contrib/
Each pattern matches its directory at any depth. The scan then covers the code your team writes, so a clean install reports no findings while Gitleaks still detects real secrets.
Ignoring
To ignore a single line you can edit, add a gitleaks:allow comment to it.
Gitleaks skips every finding on a line that contains the comment, so the
exception moves with the line:
$settings['example'] = 'not-a-real-secret'; // gitleaks:allow
For other exceptions, use 1 of the following:
- To ignore a path or a known-safe value that recurs across the codebase,
add an allowlist entry to the
.gitleaks.tomlfile. - To ignore 1 finding on a line that can't hold a comment, such as a line
in a JSON file, add its fingerprint to a
.gitleaksignorefile at the repository root. The fingerprint names the file, the rule, and the line number, so it stops matching when the line moves.
Copy the fingerprint from the Fingerprint: line that gitleaks dir . -v
prints for the finding. The file takes 1 fingerprint per line and skips
blank lines and lines that start with #:
# Fake token in a Behat fixture.
tests/behat/fixtures/response.json:generic-api-key:3
Confirm that the exception works: run gitleaks dir . -v again and check
that the finding no longer appears. When it was the only finding, the scan
ends with no leaks found.
Scanning the Git history
The CI scan reads the files in the checkout. A secret committed in 1 commit
and deleted in the next passes that scan, but anyone with a clone can still
read it from the history. gitleaks git scans the lines each commit added,
so it finds those secrets too.
A history scan gives the same answer for the same commits and rules, so CI
doesn't run it on every build. Run it yourself at the points in the
following sections. Run it from the project root, so Gitleaks reads
.gitleaks.toml and .gitleaksignore the same way gitleaks dir does.
Onboarding scan
Scan the full history once when you add secret scanning to a repository that already has commits, for example when you adopt Vortex on an existing project:
gitleaks git . -v --redact
--redact replaces each matched secret with REDACTED in the output. The
rest of the source line still appears, so treat the output as sensitive and
don't share it. The output also shows the file, line, commit, and
fingerprint of each finding.
Gitleaks scans only the commits and branches present in your clone. A clone
made with git clone --depth holds part of the history and 1 branch, so
clone the repository again without --depth before you scan.
Handle each finding as described in
Handling a finding in the history.
Then run the scan again and confirm that it ends with no leaks found.
Ad hoc scans
Scan the history again in these cases:
-
Before you merge a branch where a secret might have been committed and then removed. Check out the branch, then pass a Git revision range to
--log-optsto scan only its commits:gitleaks git . -v --redact --log-opts="origin/main..HEAD"Replace
origin/mainwith your default branch.HEADis the checked-out branch, so the range is empty when you run the scan from the default branch. -
Before you make a private repository public. Every commit becomes readable, including commits that exist only in closed pull requests. GitHub keeps those under
refs/pull/, so fetch every branch, every tag, and those refs before you scan the full history:git fetch --tags origingit fetch origin "+refs/pull/*:refs/remotes/origin/pull/*" -
After a Gitleaks upgrade or a rule change in
.gitleaks.toml. A new rule can match content in old commits, and only a history scan checks them.
Handling a finding in the history
A secret in the history stays exposed for as long as the credential works. To close the exposure, rotate the credential:
- Revoke the credential with the service that issued it.
- Create a new credential.
- Update every place that uses the credential.
Rotate the credential rather than rewriting the history. A rewrite leaves the secret in existing clones, forks, CI caches, and the hosting provider's pull request references. After rotation, the old value in the history no longer grants access.
After you rotate the credential, add the finding's fingerprint to
.gitleaksignore as described in Ignoring, so later history
scans pass. A history fingerprint starts with the commit hash, so it
matches the finding in that commit only:
# GitHub token revoked and rotated.
06d02de9fdcbeac96844a410462a26f3fc5c9004:web/sites/default/settings.php:github-pat:2
Continuous integration
Gitleaks runs from its official Docker image in the security audit
workflow and fails
that workflow when it finds a secret. The installer turns the scan on by
default. Answering no at its
Scan for committed secrets with Gitleaks? prompt removes the CI steps
and the .gitleaks.toml file.
Ignoring failures
Set VORTEX_CI_GITLEAKS_IGNORE_FAILURE to 1 to let the workflow pass
anyway. Gitleaks still runs and reports how many findings it made. In
GitHub Actions, the details reach code scanning and the security-findings
artifact; in CircleCI, run gitleaks dir . -v locally to see them.
➡️ See Ignore tool failures.
Where findings appear
In GitHub Actions, the workflow also uploads Gitleaks findings to the
repository's Security → Code scanning tab under the gitleaks category.
Each finding becomes an alert naming the rule that matched, located at the
line it was found on.
➡️ See Code scanning.
Dismissing a finding
Dismissing an alert in the Security → Code scanning tab records a reason against that finding and removes it from the open list. That's the right tool for tracking an assessment.
It doesn't change what the scan does. Gitleaks still matches the value and
still fails the workflow until you ignore it as described in
Ignoring. That takes a gitleaks:allow comment on the line, an
allowlist entry in .gitleaks.toml, or the finding's fingerprint in
.gitleaksignore.