Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

TruffleHog: detect secrets exposed in your code and infrastructure

By updated

Improve this page

Logo TruffleHog

TruffleHog detects the secrets exposed in your Git repositories, Docker images, cloud buckets and more. Its README announces more than 800 recognized secret types; it automatically verifies, with the provider, whether the credentials it finds are active. It helps keep your API keys, tokens and passwords from ending up on GitHub.

What you will learn

  • Understand how TruffleHog detects and verifies secrets
  • Scan different sources: Git, Docker, S3, Jenkins, Elasticsearch
  • Filter the results to reduce false positives
  • Integrate TruffleHog into your CI/CD pipelines (GitHub Actions, GitLab CI)
  • Understand what the permission analysis of a discovered secret brings
  • Tie the lesson to the SOCLE: the requirement SOCLE-SEC-GEN-6 (in French), secret leak detection and response procedure, finds its detection tooling here.

The problem of secrets in code

A secret pushed to a public repository is quickly spotted: bots continuously crawl GitHub's public events and test the keys they find. With a cloud account key, an attacker can for example start machines billed to its owner to mine cryptocurrency. This is the scenario these scanners aim to prevent.

Secrets end up exposed for several reasons:

SituationExampleRisk
Committed config file.env missing from .gitignorePlaintext API keys in the Git history
Hardcoded passwordpassword = "admin123" in the codeAccess to the database
Token in the logsAuthorization: Bearer sk_live_...Account compromise
Secret in a Docker imageSSL certificate in /app/certs/Traffic interception
Git historySecret deleted but present in an old commitStill reachable through git log

Deleting a secret from the code does not erase it from the Git history, and malicious scanners analyse the whole history, not just the main branch.

How TruffleHog solves this problem

TruffleHog does not merely look for patterns with regexes (regular expressions). It follows a four-step process: discovery, classification, verification, analysis.

Discovery: where to look?

TruffleHog scans far more than Git repositories. It analyses fifteen different sources, read from its code on 2026-10-29, which cover the whole development cycle:

SourceCommandWhat is scanned
GitgitThe whole history, all branches
GitHubgithubRepos, orgs, issues, pull requests, gists
GitLabgitlabRepos, groups, snippets
DockerdockerLocal or registry images, layers
FilesystemfilesystemLocal files and directories
S3s3AWS S3 buckets
GCSgcsGoogle Cloud Storage buckets
JenkinsjenkinsJobs, configurations, builds
ElasticsearchelasticsearchIndices and documents
PostmanpostmanCollections and environments
HuggingFacehuggingfaceModels, datasets, spaces
CircleCIcircleciConfigurations and environments
TravisCItravisciConfigurations
SyslogsyslogLog streams
stdinstdinStandard input (pipes)

Classification: what type of secret?

TruffleHog ships detectors (more than 800 secret types according to its README) able to identify the exact type of each secret. This is not just "a string that looks like a key" but a precise identification:

  • AWS Access Key (starts with AKIA...)
  • Stripe API Key (starts with sk_live_ or sk_test_)
  • GitHub Personal Access Token (starts with ghp_...)
  • RSA, DSA, ECDSA private keys
  • JWT tokens with cryptographic verification
  • Passwords in URLs (PostgreSQL, MySQL, MongoDB)

This classification matters because it determines how the secret will be verified and which remediation actions are needed.

Verification: is the secret active?

Verification is the feature TruffleHog was built around. For each detected secret, it tries to use it against the matching API to check whether it is active.

For example, for an AWS key, TruffleHog calls sts:GetCallerIdentity to see whether the key works. For a GitHub token, it calls the GitHub API. This verification sets aside the inactive secrets and shows which secrets are dangerous right now.

The results fall into three categories:

StatusMeaningAction required
verifiedThe secret worksImmediate rotation, the secret is active
unknownVerification impossibleNetwork or API error, check manually
unverifiedDetected but not verifiedMay be expired, invalid, or not verifiable

Analysis: which permissions?

For some secret types, TruffleHog goes further with its analysis command, trufflehog analyze, described by its help as analyzing API keys to get fine-grained information about their permissions. Run without an argument, it opens an interactive menu where you pick the key type among 44 analyzers in 3.99.7 (GitHub, GitLab, Slack, Stripe, OpenAI, Postgres, MySQL, among others); AWS and GCP are not in it. Instead of a plain "yes/no" on validity, it tries to find out:

  • Which account/user owns this secret
  • Which resources it can reach
  • Which permissions it has on those resources

This is used to assess the impact: a GitHub token that writes to all the repositories of an organization is far more serious than a read-only token on a single repository. The analysis queries the provider's API with the key you supply: run it only on a key you are entitled to inspect.


Installation

Several methods are available depending on your environment.

Install TruffleHog from the official binary, checking its SHA256 digest, rather than with a curl | sh script. Download the archive and the checksums file from the GitHub Releases, check the digest, then place the binary in your PATH:

Terminal window
TRUFFLEHOG_VERSION=3.99.7
cd /tmp
base="https://github.com/trufflesecurity/trufflehog/releases/download/v${TRUFFLEHOG_VERSION}"
curl -sSfLO "${base}/trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz"
curl -sSfLO "${base}/trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt"
# Check the SHA256 digest before installing
grep "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt" | sha256sum -c -
# User install into ~/.local/bin
mkdir -p ~/.local/bin
tar -C ~/.local/bin -xzf "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" trufflehog
~/.local/bin/trufflehog --version
# trufflehog 3.99.7

For a system-wide install, extract to /usr/local/bin with sudo instead:

Terminal window
sudo tar -C /usr/local/bin -xzf "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" trufflehog

Scanning a Git repository

The first use case is to scan the full history of a Git repository to find secrets that may have been committed in the past.

Basic scan

TruffleHog scans the whole Git history, including branches and commits that were deleted but are still recoverable. This is intentional: an attacker would do the same.

Terminal window
# Scan a GitHub repo
trufflehog git https://github.com/trufflesecurity/test_keys
# Show only verified (active) secrets
trufflehog git https://github.com/trufflesecurity/test_keys --results=verified

Here is a sample output, with a verified secret:

🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷
Found verified result 🐷🔑
Detector Type: AWS
Decoder Type: PLAIN
Raw result: AKIAYVP4CIPPERUVIFXG
Line: 4
Commit: fbc14303ffbf8fb1c2c1914e8dda7d0121633aca
File: keys
Email: counter <counter@counters-MacBook-Air.local>
Repository: https://github.com/trufflesecurity/test_keys
Timestamp: 2022-06-16 10:17:40 -0700 PDT

This output tells you:

  • The secret type: AWS Access Key
  • The location: file keys, line 4
  • When: commit of 16 June 2022
  • By whom: the email of the commit author

With 3.99.7, the text output can carry extra lines. They come from the detector's complementary data: for an AWS key, Resource_type, Account and Message, as well as Is_canary: true when the key is a canary token, that is, a decoy credential that alerts its owner as soon as it is used. A repository cloned locally adds Repository_local_path.

Understanding the filtering options

TruffleHog offers several options to refine the results and reduce noise:

Terminal window
# Show only verified secrets (recommended for triage)
trufflehog git <URL> --results=verified
# Show verified + unknown (verification errors)
trufflehog git <URL> --results=verified,unknown
# Show everything (including potential false positives)
trufflehog git <URL> --results=verified,unverified,unknown
# Disable verification (faster, but more false positives)
trufflehog git <URL> --no-verification
# Filter by entropy (reduce false positives on random strings)
trufflehog git <URL> --filter-entropy=3.0

Scanning a local repo

To scan a locally cloned repo, use the file:// protocol:

Terminal window
# Clone the repo
git clone https://github.com/exemple/mon-projet.git
cd mon-projet
# Scan (from the repo's parent directory)
cd ..
trufflehog git file://mon-projet --results=verified,unknown

Scanning a whole GitHub organization

To audit all the repos of an organization:

Terminal window
# Without authentication (limited by rate limiting)
trufflehog github --org=mon-organisation --results=verified
# With a GitHub token (recommended), read from the GITHUB_TOKEN variable
read -rsp "GitHub token: " GITHUB_TOKEN && export GITHUB_TOKEN
trufflehog github --org=mon-organisation --results=verified
# Include issues and pull requests
trufflehog github --org=mon-organisation --issue-comments --pr-comments

A GitHub token is strongly recommended, because unauthenticated scans are limited to 60 requests per hour against 5000 with a token. TruffleHog reads the GITHUB_TOKEN variable by itself: there is no need to repeat the token in the --token option, where it would appear in the process list. Typing it with read -rs also keeps it out of the shell history.


Scanning other sources

Docker images

Docker images can hold secrets in their layers: certificates, configuration files, environment variables.

Terminal window
# Scan an image from a registry
trufflehog docker --image nginx:1.29.3@sha256:2f4e10193b0c4f61472245e9d26cea78e7df7af266c7e7cf5e67353ee2731b51
# Scan a local image (docker:// prefix)
trufflehog docker --image docker://mon-image:1.4.0
# Scan several images
trufflehog docker --image postgres:15@sha256:64b99032e218b66b1d1a6334995056e1aa57f50a0c522cc856e72dff0e4b0d63 \
--image redis:7@sha256:b6b6e3dc0c0952737748e55d5d885272840c7e42ba41ab1d5489f693419882f5
# Scan an image exported as a tarball
trufflehog docker --image file://path/to/image.tar

TruffleHog analyses each layer of the image, which makes it possible to find secrets even if they were "deleted" in a later layer, a classic mistake in Dockerfiles.

S3 buckets

To scan AWS S3 buckets, TruffleHog uses the AWS credentials of your environment (environment variables, the ~/.aws/credentials file, or an IAM role).

Terminal window
# Scan a specific bucket
trufflehog s3 --bucket=mon-bucket-data
# Scan with an IAM role (cross-account)
trufflehog s3 --bucket=bucket-autre-compte --role-arn=arn:aws:iam::123456789012:role/TruffleHogRole
# Scan all the buckets reachable through several roles
trufflehog s3 --role-arn=arn:aws:iam::111111111111:role/Role1 --role-arn=arn:aws:iam::222222222222:role/Role2

Google Cloud Storage buckets

For GCS, authenticate with gcloud auth login or a credentials file:

Terminal window
# Scan a whole GCS project
trufflehog gcs --project-id=mon-projet-gcp --cloud-environment
# Show only verified secrets
trufflehog gcs --project-id=mon-projet-gcp --results=verified

Jenkins

Jenkins job configurations can contain secrets. Pass the API token through the JENKINS_PASSWORD variable, which TruffleHog reads by itself, rather than as an option where it would stay in the shell history:

Terminal window
read -rsp "Jenkins API token: " JENKINS_PASSWORD && export JENKINS_PASSWORD
trufflehog jenkins --url https://jenkins.mon-entreprise.fr --username admin

Elasticsearch

To scan Elasticsearch data, the password goes the same way, through the ELASTICSEARCH_PASSWORD variable:

Terminal window
# Local cluster with basic authentication
read -rsp "elastic password: " ELASTICSEARCH_PASSWORD && export ELASTICSEARCH_PASSWORD
trufflehog elasticsearch --nodes 192.168.1.10 --username elastic
# Elastic Cloud: the API key goes through ELASTICSEARCH_API_KEY
read -rsp "Elastic API key: " ELASTICSEARCH_API_KEY && export ELASTICSEARCH_API_KEY
trufflehog elasticsearch --cloud-id 'mon-cluster:dXMtY2VudHJhbD...'

HuggingFace

Since v3.88, TruffleHog can scan HuggingFace models, datasets and spaces:

Terminal window
# Scan a specific model
trufflehog huggingface --model meta-llama/Llama-2-7b
# Scan a whole organization
trufflehog huggingface --org huggingface
# Include discussions and PRs
trufflehog huggingface --model mon-modele --include-discussions --include-prs

Local files

To scan local files or directories (logs, exports, configs):

Terminal window
# Scan a directory
trufflehog filesystem /path/to/folder
# Scan specific files
trufflehog filesystem file1.log file2.env /etc/config/
# Disable verification (quick scan)
trufflehog filesystem /var/log --no-verification

Standard input (stdin)

Useful for pipelines and for analysing data that is decompressed on the fly:

Terminal window
# Scan a compressed S3 file on the fly
aws s3 cp s3://mon-bucket/logs.gz - | gunzip -c | trufflehog stdin
# Scan the output of a command
kubectl logs deployment/mon-app | trufflehog stdin

Outputs and formats

Text format (default)

The colored text format is readable by humans:

Found verified result 🐷🔑
Detector Type: AWS
Raw result: AKIAYVP4CIPPERUVIFXG
File: keys
Line: 4

JSON format

For integration into tools or scripts, use --json:

Terminal window
trufflehog git <URL> --results=verified --json

Sample JSON output:

{
"SourceMetadata": {
"Data": {
"Git": {
"commit": "fbc14303ffbf8fb1c2c1914e8dda7d0121633aca",
"file": "keys",
"line": 4,
"repository": "https://github.com/trufflesecurity/test_keys"
}
}
},
"DetectorType": 2,
"DetectorName": "AWS",
"Verified": true,
"Raw": "AKIAYVP4CIPPERUVIFXG",
"Redacted": "AKIAYVP4CIPPERUVIFXG",
"ExtraData": {
"account": "595918472158",
"arn": "arn:aws:iam::595918472158:user/leaked-user"
}
}

This excerpt is deliberately shortened. Version 3.99.7 adds to each result SourceID, SourceType and SourceName, DetectorDescription (a sentence describing the targeted service), DecoderName, VerificationFromCache, RawV2 and StructuredData. Since v3.95.7, the result also carries SecretParts, the separate parts of the secret (for an AWS key, access_key_id and secret_access_key). These fields hold the secret in plaintext: treat a trufflehog.json file as a secret, and do not publish it as an artifact accessible to everyone.

SARIF format

The SARIF format (Static Analysis Results Interchange Format) is the exchange format that GitHub code scanning can read. The --sarif option, available since v3.97.0, writes it to standard output, the logs staying on the error output:

Terminal window
trufflehog git <URL> --results=verified,unknown --sarif > trufflehog.sarif

GitHub Actions format

For native integration into GitHub Actions with annotations:

Terminal window
trufflehog git <URL> --github-actions

CI/CD integration

GitHub Actions

TruffleHog offers an official action that automatically scans PRs and pushes:

name: TruffleHog Secrets Scan
on:
push:
branches: [main]
pull_request:
permissions: {}
jobs:
trufflehog:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # Important: fetch the whole history
persist-credentials: false
- name: TruffleHog Scan
uses: trufflesecurity/trufflehog@31ce31ee1abbcc7dc8eee5764c17121c3044c8b2 # v3.99.7
with:
extra_args: --results=verified,unknown

The action scans the commits of the PR (pull request) or of the push. fetch-depth: 0 is essential to analyse the full history. The workflow removes every default permission (permissions: {}), gives the job back only read access to the repository, and persist-credentials: false avoids leaving the checkout token on the runner's disk.

To scan only the new commits, which is faster, give the base branch and HEAD:

- name: TruffleHog OSS
uses: trufflesecurity/trufflehog@31ce31ee1abbcc7dc8eee5764c17121c3044c8b2 # v3.99.7
with:
base: ${{ github.event.repository.default_branch }}
head: HEAD
extra_args: --results=verified,unknown --fail

GitLab CI

Integrate TruffleHog into your GitLab merge requests:

stages:
- security
trufflehog-scan:
stage: security
image: alpine:3.24.1@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b
variables:
SCAN_PATH: "."
before_script:
- apk add --no-cache git curl tar
- TRUFFLEHOG_VERSION=3.99.7
- base="https://github.com/trufflesecurity/trufflehog/releases/download/v${TRUFFLEHOG_VERSION}"
- curl -sSfLO "${base}/trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz"
- curl -sSfLO "${base}/trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt"
- grep "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt" | sha256sum -c -
- tar -C /usr/local/bin -xzf "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" trufflehog
script:
- trufflehog filesystem "$SCAN_PATH" --results=verified,unknown --fail --json > trufflehog.json
artifacts:
when: always
paths:
- trufflehog.json
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
allow_failure: false

The --fail option returns code 183 if secrets are found, which fails the pipeline. Do not redirect its output to a pipe such as | jq: the sh shell of the Alpine image then returns the code of the last command of the pipe, and the job would turn green despite the secrets. The JSON report therefore goes to a file, kept as an artifact even when the job fails.

Pre-commit hook

Block secrets before they are committed:

.pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: trufflehog
name: TruffleHog
description: Detect secrets in your commits
entry: bash -c 'trufflehog git file://. --since-commit HEAD --results=verified,unknown --fail'
language: system
stages: ["pre-commit", "pre-push"]

The hook only scans the changes indexed since HEAD (--since-commit HEAD), which makes it fast. This configuration relies on the pre-commit framework (in French), which installs and runs your repository's hooks.


Advanced filtering and configuration

Before the filters, two reading behaviours to know. TruffleHog decodes encoded content (base64, UTF-16, escapes) before searching, and it goes down into archives within the limits set by --archive-max-depth and --archive-max-size. An encoded secret, or one stored in an archive, is therefore found without any particular setting, within those limits.

Excluding files or paths

Create a file that lists the paths to ignore, one per line. Each line is a regular expression, not a glob pattern: *.md would be an invalid regex there, you have to write \.md$. Lines that start with # are comments:

exclusions.txt
# Test files
^tests/
_test\.go$
\.test\.js$
# Fixtures and mocks
^fixtures/
/mocks/
# Documentation
^docs/
\.md$

Use it with --exclude-paths:

Terminal window
trufflehog git <URL> --exclude-paths=exclusions.txt

Including only certain files

The reverse is also possible with --include-paths, which expects the same regular expression format:

inclusions.txt
# Scan only the config files
\.env$
\.ya?ml$
\.json$
^config/
Terminal window
trufflehog git <URL> --include-paths=inclusions.txt

Selecting specific detectors

If you are looking for a particular type of secret:

Terminal window
# Look for AWS keys only
trufflehog git <URL> --include-detectors=AWS
# Look for AWS and GitHub
trufflehog git <URL> --include-detectors=AWS,GitHub
# Exclude the private key detectors (many false positives)
trufflehog git <URL> --exclude-detectors=PrivateKey

Ignoring specific secrets

To ignore a known secret (canary token, test key), add a trufflehog:ignore comment on the same line:

# This key is a canary token for intrusion detection
AWS_KEY = "AKIAIOSFODNN7EXAMPLE" # trufflehog:ignore

To check that these markers do not hide real secrets, the --no-ignore-tag option (since v3.98.0) also brings back the marked lines.

Configuration file

The configuration file passed through --config carries only two things: custom detectors and sources. It is read in strict mode, and an unknown key such as options: makes it get refused at load time. The choice of detectors, the filtering of results and the failure of the scan therefore go through the command line:

Terminal window
trufflehog git <URL> \
--include-detectors=AWS,GitHub,Slack,Stripe \
--exclude-detectors=PrivateKey \
--results=verified,unknown \
--fail --concurrency=8

To avoid retyping these options, put this line in a script or a Makefile target: it, and not the --config file, sets the behaviour of the scan.


Custom detectors

TruffleHog lets you define your own detectors with regexes and a verification point (endpoint). This is the real use of the --config file. Note that verify is a list: each entry starts with a dash, even if there is only one endpoint.

custom-detectors.yaml
detectors:
- name: InternalAPIKey
keywords:
- "X-Internal-Key"
- "internal_api"
regex:
secret: 'int_[a-zA-Z0-9]{32}'
verify:
- endpoint: https://verify.mon-entreprise.fr/check
unsafe: false
headers:
- 'Content-Type: application/json'

Use it with:

Terminal window
trufflehog git <URL> --config=custom-detectors.yaml

The verification endpoint receives a POST with the captured groups and must return 200 if the secret is valid.


Troubleshooting

When a scan misbehaves, start from the observed symptom: the table gives the likely causes and the option that fixes them. An unknown on all the results most often points to a blocked network to the verification APIs, not to the absence of secrets.

SymptomLikely causeSolution
No result displayedClean repository, truncated clone in CI, or --results filter too strictCheck fetch-depth: 0 and widen --results before concluding
Very slow scanLarge Git historyUse --max-depth=100
Rate limiting errorGitHub API saturatedSet GITHUB_TOKEN with a PAT
Many false positivesTest secrets, fixturesUse --results=verified or --exclude-paths
permission denied on DockerNo access to the Docker socketAdd the user to the docker group
unknown for all resultsNetwork blocked to the APIsCheck the proxy/firewall
git clone timeout errorVery large repoIncrease with --git-clone-timeout=30m

Debug logs

To understand what TruffleHog is doing:

Terminal window
# Info level (default)
trufflehog git <URL> --log-level=0
# Debug level
trufflehog git <URL> --log-level=2
# Trace level (very verbose)
trufflehog git <URL> --log-level=5

Best practices

The three areas below follow the order of value of a defense: prevention first, detection next, remediation as a last resort, because at that stage the secret is already compromised.

Prevention: keep secrets out of Git

These four measures reinforce one another, but the most decisive is the secrets manager: as long as a secret exists in plaintext in a file on the workstation, it will sooner or later be committed by accident. Hooks and .gitignore catch the mistake, the secrets manager makes it unlikely.

  1. Pre-commit hooks: block commits that contain secrets
  2. .gitignore files: exclude .env, *.pem, credentials.json
  3. Secrets manager: use OpenBao (in French), Vault, AWS Secrets Manager or Passbolt (in French); SOPS encrypts the secrets that must stay in Git
  4. Environment variables: inject secrets at runtime, not in the code

Detection: scan regularly

The pull request scan and the periodic scan do not look for the same thing: the first judges the changes of the PR and must stay fast, the second goes over the full history again to catch what yesterday's detectors did not know.

  1. CI/CD: scan every PR and push
  2. Periodic scans: audit the whole organization every week
  3. New repos: add TruffleHog from creation

Remediation: react to findings

  1. Immediate rotation: revoke and recreate the exposed secret
  2. Access audit: check the usage logs of the compromised secret
  3. History cleanup: use git filter-repo, which the Git documentation recommends in place of git filter-branch, or BFG Repo-Cleaner
  4. Post-mortem: understand how the secret was exposed

Gitleaks, Betterleaks, TruffleHog or Kingfisher: which one should you choose?

TruffleHog is the one of the four that was built around verification: each recognized secret is tested with the provider before being reported as active. The table compares it with Gitleaks, frozen since its author develops Betterleaks, and with Kingfisher, which extends verification with mapping and revocation.

The table compares the four scanners on what matters when you choose: where they look, what they do with a secret they find, and how they fit into a delivery pipeline. Every cell comes from the tool's own documentation at the version shown in the header. When that documentation says nothing about a capability, the cell reads "not documented": this does not prove the tool is unable to do it, only that its documentation does not announce it.

CriterionGitleaks 8.30.1Betterleaks 1.9.0TruffleHog 3.99.7Kingfisher 2.16.0
Git repository and historyyes, gitleaks git (via git log -p)yes, betterleaks gityes, trufflehog gityes, history included
Remote repository, organizationnot documented (three modes: git, dir, stdin)GitHub (organization, user, PRs, issues, Actions, releases), GitLab (group, project, merge requests), Hugging FaceGitHub (--org), GitLab, Hugging FaceGitHub, GitLab, Azure Repos, Bitbucket, Gitea, Hugging Face
Files and directoriesyes, gitleaks diryes, betterleaks diryes, trufflehog filesystemyes
Container imagenot documentednot documentedyes, trufflehog dockeryes, kingfisher scan docker
Other sourcesstandard inputstandard input, S3 (including Cloudflare R2)S3, GCS, Postman, Jenkins, Elasticsearch, CircleCI, Travis CI, syslog, standard inputS3, GCS, Azure Blob Storage, Jira, Confluence, Slack, Teams, Postman
Checks that a secret is activenot documentedyes, through a validate expression in the rule, opt-in only, --validation in 1.9.0 (-v or --validate in version 2); statuses valid, invalid, revoked, unknown, erroryes, by calling the provider's API, enabled by default (--no-verification turns it off)yes, enabled by default (--no-validate turns it off)
Measures the blast radiusnot documentednot documented in 1.9.0; the version 2 preview adds -a or --analyze (account, capabilities and severity of valid tokens)yes, trufflehog analyze (permissions and reachable resources) for some credential typesyes, --blast-radius for the supported providers (identities, permissions, resources)
Revokes a secretnot documentednot documented in 1.9.0 (revocation only appears there as a status returned by validation); the version 2 preview announces betterleaks revokenot documentedyes, kingfisher revoke, for the supported providers
Pre-commit hookyes, pre-commit hooks providedyes, pre-commit hooks providedyes, documented (hooksPath, pre-commit framework, Husky)yes, install script and pre-commit framework
CI integrationgitleaks-action action (separate repository), Docker imageDocker image ghcr.io/betterleaks/betterleaks; no dedicated action in the READMEGitHub action trufflesecurity/trufflehog, Docker imageDocker image ghcr.io/mongodb/kingfisher; no dedicated action in the documentation
Output formatsJSON, CSV, JUnit, SARIF, templateJSON, CSV, JUnit, SARIF, template (JSONL for validate)text, JSON, SARIF, GitHub Actions formathuman-readable text, JSON, JSONL, BSON, TOON, SARIF, HTML
LicenseMITMITAGPL-3.0Apache-2.0
LanguageGoGoGoRust

Survey carried out on 2026-10-30 on the latest published version of each tool. Versions move fast: check the date before relying on a cell.

The right tool depends first on what you want to do with a secret once it is found. To block a commit or a merge, all four will do, and Gitleaks is enough when its rules are mastered and it is already in place. To tell live secrets from leftover examples, you need a tool that validates: Betterleaks (opt-in), TruffleHog or Kingfisher. To know what an active token opens up, TruffleHog (analyze) and Kingfisher (--blast-radius) answer, each on the providers it supports; Betterleaks adds a comparable analysis in its version 2, still a preview. To act without waiting for the owner of the secret, only Kingfisher documents revocation from the command line in the stable versions surveyed; Betterleaks announces one for its version 2 as well.

If the target goes beyond the repository (issues, chat, images, buckets), look at the "Other sources" row: the scope varies a lot from one tool to another. An AGPL-3.0 license can also weigh in the choice depending on how your organization uses the tool. Finally, a scanner that finds nothing proves nothing: test the one you pick on a repository containing a known fake secret before wiring it into CI. To freeze what already exists and block only new findings, the detect-secrets guide (in French) covers a baseline approach, and the comparison of secret detection tools widens the view to other candidates.


Key points

  1. TruffleHog tests whether each secret works, which sets inactive secrets aside from triage.
  2. It reads fifteen sources, from Git to Docker, S3, Jenkins, Elasticsearch or HuggingFace, and classifies more than 800 secret types (AWS, GitHub, Stripe, Slack, Postgres...).
  3. It scans the whole history: all commits, all branches.
  4. The verified, unknown and unverified statuses are not handled the same way: only verified is certain, the other two call for a review.
  5. --results=verified keeps only the active secrets: it is the basic triage option.
  6. A pre-commit hook blocks secrets before they are committed.
  7. An exposed secret is a compromised secret: immediate rotation.
  8. For the SOCLE-SEC-GEN-6 requirement, the expected evidence is a detection system, here a TruffleHog scan wired as a hook and in CI on your repositories, together with a written response procedure: who revokes, who renews, within what time. The scanner only provides the first half of this evidence.

Resources

The links below lead to the official sources: the project repository, the list of detectors and the GitHub action used in this guide.

Knowledge check

Check that you have the essentials of this guide. The questions only cover what has just been explained here.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn