TruffleHog
.mdVerified against TruffleHog 3.97.1, flags verified via `trufflehog --help` run locally, 2026-08-29 · official docs
What it is and where it fits 🎯#
TruffleHog does secret detection with live verification — it doesn't just pattern-match a string that looks like a key, it actually calls the relevant provider's API to check whether the credential is still active. This is the single biggest practical difference from Gitleaks: dramatically fewer false positives, because "this matched an AWS-key-shaped regex" and "this IS a working AWS key right now" are very different signals to hand a security team. The tradeoff is real too — verification makes outbound network calls per candidate secret, which is slower and means TruffleHog needs network egress from wherever it runs (a locked-down CI runner with no outbound internet access can't verify anything).
How verification changes the signal ⚙️#
Installation#
curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh \
| sh -s -- -b /usr/local/bin
brew install trufflehog
trufflehog --versionScanning a git repository#
trufflehog git file://. # local repo, full history
trufflehog git https://github.com/org/repo.git # remote, clones internally
trufflehog git file://. --since-commit HEAD~20 # limit history depthScanning a filesystem (no git)#
trufflehog filesystem /path/to/project
trufflehog filesystem file1.txt file2.txtScanning platforms directly#
trufflehog github --org=my-org # every repo in a GitHub org
trufflehog github --repo=https://github.com/org/repo
trufflehog gitlab --token=$GITLAB_TOKEN
trufflehog s3 --bucket=my-bucket
trufflehog docker --image=myapp:latestTip
Scanning an entire GitHub org (trufflehog github --org=my-org) is a genuinely useful one-time audit —
most secrets scanners are wired into a single repo's pipeline, but a leaked credential from three years ago
in a long-forgotten internal tools repo is exactly the kind of thing an org-wide sweep surfaces that
per-repo CI gates never will.
Filtering to only verified secrets — the flag that matters most#
trufflehog git file://. --only-verified # only report secrets confirmed live against the provider
trufflehog git file://. --results=verified,unverified # default; narrow this down for less noise
trufflehog git file://. --no-verification # skip verification entirely — faster, but back to pattern-matching noiseImportant
--only-verified is what makes TruffleHog usable as a hard CI gate instead of a noisy report — an
unverified match might be a false positive or an already-rotated credential; a verified one is a live,
exploitable secret right now, which is a materially different severity to hand a team.
Output and CI gating#
trufflehog git file://. --json
trufflehog git file://. --fail # exit code 183 if any results are found — for pipeline gating
trufflehog git file://. --github-actions # GitHub Actions annotation format
trufflehog git file://. --sarif # for GitHub code scanning uploadSample JSON finding shape (illustrative — actual detector names/fields evolve with the tool's release, this shows the shape of a verified result, not a literal captured record):
{
"SourceMetadata": {
"Data": {
"Git": {
"commit": "a1b2c3d4...",
"file": "config/settings.py",
"line": 42
}
}
},
"DetectorName": "AWS",
"Verified": true,
"Raw": "AKIA****************"
}Tuning detectors and performance#
trufflehog git file://. --include-detectors=aws,github,slack # only run specific detector types
trufflehog git file://. --exclude-detectors=generic # skip noisy generic entropy-based detectors
trufflehog git file://. --concurrency=8
trufflehog git file://. --archive-max-depth=2 # scan inside nested archives tooReal-world scenario: incident response after an accidental push#
A credential just got pushed to a public repo. Speed matters — the window between push and rotation is the window an attacker has:
trufflehog git file://. --since-commit HEAD~1 --only-verified --failCaution
A verified TruffleHog hit means the credential is confirmed live at the moment of the scan — treat it as an
active incident: rotate immediately, don't wait to "confirm" further, and only then clean the git history
(git filter-repo or BFG) since the secret must be assumed compromised the instant it was pushed to a
shared repository, regardless of whether history gets rewritten afterward.
Real-world scenario: GitHub Actions CI gate#
# .github/workflows/trufflehog.yml
name: TruffleHog
on: [pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: trufflesecurity/trufflehog@main
with:
extra_args: --only-verifiedCommon pitfalls#
- Running in a network-isolated CI runner — verification needs outbound calls to each provider's API; an air-gapped runner silently degrades every result to unverified (or errors, depending on the detector).
- Treating an unverified result as low-priority by default —
--results=verified,unverified,unknownis the actual default; unverified findings still deserve a look, they just shouldn't hard-fail a build the way a verified one should. - Confusing exit code 183 with a standard
1— script against the documented code specifically, not an assumption of1/0.
Exit codes#
0 clean (or found-but---fail not set) · 183 findings found, with --fail set.
When to reach for something else#
Gitleaks is faster and needs no network egress — the right choice for an air-gapped or latency-sensitive pre-commit hook. Reach for TruffleHog specifically when false-positive noise from pattern-only matching is a real problem, or when incident response needs a fast "is this credential I found still live" answer.