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:
| Situation | Example | Risk |
|---|---|---|
| Committed config file | .env missing from .gitignore | Plaintext API keys in the Git history |
| Hardcoded password | password = "admin123" in the code | Access to the database |
| Token in the logs | Authorization: Bearer sk_live_... | Account compromise |
| Secret in a Docker image | SSL certificate in /app/certs/ | Traffic interception |
| Git history | Secret deleted but present in an old commit | Still 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:
| Source | Command | What is scanned |
|---|---|---|
| Git | git | The whole history, all branches |
| GitHub | github | Repos, orgs, issues, pull requests, gists |
| GitLab | gitlab | Repos, groups, snippets |
| Docker | docker | Local or registry images, layers |
| Filesystem | filesystem | Local files and directories |
| S3 | s3 | AWS S3 buckets |
| GCS | gcs | Google Cloud Storage buckets |
| Jenkins | jenkins | Jobs, configurations, builds |
| Elasticsearch | elasticsearch | Indices and documents |
| Postman | postman | Collections and environments |
| HuggingFace | huggingface | Models, datasets, spaces |
| CircleCI | circleci | Configurations and environments |
| TravisCI | travisci | Configurations |
| Syslog | syslog | Log streams |
| stdin | stdin | Standard 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_orsk_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:
| Status | Meaning | Action required |
|---|---|---|
| verified | The secret works | Immediate rotation, the secret is active |
| unknown | Verification impossible | Network or API error, check manually |
| unverified | Detected but not verified | May 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:
TRUFFLEHOG_VERSION=3.99.7cd /tmpbase="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 installinggrep "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt" | sha256sum -c -
# User install into ~/.local/binmkdir -p ~/.local/bintar -C ~/.local/bin -xzf "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" trufflehog~/.local/bin/trufflehog --version# trufflehog 3.99.7For a system-wide install, extract to /usr/local/bin with sudo instead:
sudo tar -C /usr/local/bin -xzf "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" trufflehogWith Homebrew:
brew install trufflehog
# Checktrufflehog --versionThe Docker image suits CI well, with the version and the digest pinned:
# Scan a GitHub repodocker run --rm -it trufflesecurity/trufflehog:3.99.7@sha256:0d003fc3abc4e1565eca8462b992001314de51451e96e3c44de80d116794d5d1 \ github --repo https://github.com/trufflesecurity/test_keys
# Scan a local directorydocker run --rm -it -v "$PWD:/pwd" trufflesecurity/trufflehog:3.99.7@sha256:0d003fc3abc4e1565eca8462b992001314de51451e96e3c44de80d116794d5d1 \ filesystem /pwdScanning 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.
# Scan a GitHub repotrufflehog git https://github.com/trufflesecurity/test_keys
# Show only verified (active) secretstrufflehog git https://github.com/trufflesecurity/test_keys --results=verifiedHere is a sample output, with a verified secret:
🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷
Found verified result 🐷🔑Detector Type: AWSDecoder Type: PLAINRaw result: AKIAYVP4CIPPERUVIFXGLine: 4Commit: fbc14303ffbf8fb1c2c1914e8dda7d0121633acaFile: keysEmail: counter <counter@counters-MacBook-Air.local>Repository: https://github.com/trufflesecurity/test_keysTimestamp: 2022-06-16 10:17:40 -0700 PDTThis 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:
# 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.0Scanning a local repo
To scan a locally cloned repo, use the file:// protocol:
# Clone the repogit clone https://github.com/exemple/mon-projet.gitcd mon-projet
# Scan (from the repo's parent directory)cd ..trufflehog git file://mon-projet --results=verified,unknownScanning a whole GitHub organization
To audit all the repos of an organization:
# Without authentication (limited by rate limiting)trufflehog github --org=mon-organisation --results=verified
# With a GitHub token (recommended), read from the GITHUB_TOKEN variableread -rsp "GitHub token: " GITHUB_TOKEN && export GITHUB_TOKENtrufflehog github --org=mon-organisation --results=verified
# Include issues and pull requeststrufflehog github --org=mon-organisation --issue-comments --pr-commentsA 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.
# Scan an image from a registrytrufflehog 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 imagestrufflehog docker --image postgres:15@sha256:64b99032e218b66b1d1a6334995056e1aa57f50a0c522cc856e72dff0e4b0d63 \ --image redis:7@sha256:b6b6e3dc0c0952737748e55d5d885272840c7e42ba41ab1d5489f693419882f5
# Scan an image exported as a tarballtrufflehog docker --image file://path/to/image.tarTruffleHog 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).
# Scan a specific buckettrufflehog 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 rolestrufflehog s3 --role-arn=arn:aws:iam::111111111111:role/Role1 --role-arn=arn:aws:iam::222222222222:role/Role2Google Cloud Storage buckets
For GCS, authenticate with gcloud auth login or a credentials file:
# Scan a whole GCS projecttrufflehog gcs --project-id=mon-projet-gcp --cloud-environment
# Show only verified secretstrufflehog gcs --project-id=mon-projet-gcp --results=verifiedJenkins
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:
read -rsp "Jenkins API token: " JENKINS_PASSWORD && export JENKINS_PASSWORDtrufflehog jenkins --url https://jenkins.mon-entreprise.fr --username adminElasticsearch
To scan Elasticsearch data, the password goes the same way, through the ELASTICSEARCH_PASSWORD variable:
# Local cluster with basic authenticationread -rsp "elastic password: " ELASTICSEARCH_PASSWORD && export ELASTICSEARCH_PASSWORDtrufflehog elasticsearch --nodes 192.168.1.10 --username elastic
# Elastic Cloud: the API key goes through ELASTICSEARCH_API_KEYread -rsp "Elastic API key: " ELASTICSEARCH_API_KEY && export ELASTICSEARCH_API_KEYtrufflehog elasticsearch --cloud-id 'mon-cluster:dXMtY2VudHJhbD...'HuggingFace
Since v3.88, TruffleHog can scan HuggingFace models, datasets and spaces:
# Scan a specific modeltrufflehog huggingface --model meta-llama/Llama-2-7b
# Scan a whole organizationtrufflehog huggingface --org huggingface
# Include discussions and PRstrufflehog huggingface --model mon-modele --include-discussions --include-prsLocal files
To scan local files or directories (logs, exports, configs):
# Scan a directorytrufflehog filesystem /path/to/folder
# Scan specific filestrufflehog filesystem file1.log file2.env /etc/config/
# Disable verification (quick scan)trufflehog filesystem /var/log --no-verificationStandard input (stdin)
Useful for pipelines and for analysing data that is decompressed on the fly:
# Scan a compressed S3 file on the flyaws s3 cp s3://mon-bucket/logs.gz - | gunzip -c | trufflehog stdin
# Scan the output of a commandkubectl logs deployment/mon-app | trufflehog stdinOutputs and formats
Text format (default)
The colored text format is readable by humans:
Found verified result 🐷🔑Detector Type: AWSRaw result: AKIAYVP4CIPPERUVIFXGFile: keysLine: 4JSON format
For integration into tools or scripts, use --json:
trufflehog git <URL> --results=verified --jsonSample 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:
trufflehog git <URL> --results=verified,unknown --sarif > trufflehog.sarifGitHub Actions format
For native integration into GitHub Actions with annotations:
trufflehog git <URL> --github-actionsCI/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,unknownThe 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 --failGitLab 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: falseThe --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:
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:
# Test files^tests/_test\.go$\.test\.js$
# Fixtures and mocks^fixtures//mocks/
# Documentation^docs/\.md$Use it with --exclude-paths:
trufflehog git <URL> --exclude-paths=exclusions.txtIncluding only certain files
The reverse is also possible with --include-paths, which expects the same regular expression format:
# Scan only the config files\.env$\.ya?ml$\.json$^config/trufflehog git <URL> --include-paths=inclusions.txtSelecting specific detectors
If you are looking for a particular type of secret:
# Look for AWS keys onlytrufflehog git <URL> --include-detectors=AWS
# Look for AWS and GitHubtrufflehog git <URL> --include-detectors=AWS,GitHub
# Exclude the private key detectors (many false positives)trufflehog git <URL> --exclude-detectors=PrivateKeyIgnoring 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 detectionAWS_KEY = "AKIAIOSFODNN7EXAMPLE" # trufflehog:ignoreTo 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:
trufflehog git <URL> \ --include-detectors=AWS,GitHub,Slack,Stripe \ --exclude-detectors=PrivateKey \ --results=verified,unknown \ --fail --concurrency=8To 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.
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:
trufflehog git <URL> --config=custom-detectors.yamlThe 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.
| Symptom | Likely cause | Solution |
|---|---|---|
| No result displayed | Clean repository, truncated clone in CI, or --results filter too strict | Check fetch-depth: 0 and widen --results before concluding |
| Very slow scan | Large Git history | Use --max-depth=100 |
| Rate limiting error | GitHub API saturated | Set GITHUB_TOKEN with a PAT |
| Many false positives | Test secrets, fixtures | Use --results=verified or --exclude-paths |
permission denied on Docker | No access to the Docker socket | Add the user to the docker group |
unknown for all results | Network blocked to the APIs | Check the proxy/firewall |
git clone timeout error | Very large repo | Increase with --git-clone-timeout=30m |
Debug logs
To understand what TruffleHog is doing:
# Info level (default)trufflehog git <URL> --log-level=0
# Debug leveltrufflehog git <URL> --log-level=2
# Trace level (very verbose)trufflehog git <URL> --log-level=5Best 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.
- Pre-commit hooks: block commits that contain secrets
.gitignorefiles: exclude.env,*.pem,credentials.json- Secrets manager: use OpenBao (in French), Vault, AWS Secrets Manager or Passbolt (in French); SOPS encrypts the secrets that must stay in Git
- 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.
- CI/CD: scan every PR and push
- Periodic scans: audit the whole organization every week
- New repos: add TruffleHog from creation
Remediation: react to findings
- Immediate rotation: revoke and recreate the exposed secret
- Access audit: check the usage logs of the compromised secret
- History cleanup: use
git filter-repo, which the Git documentation recommends in place ofgit filter-branch, or BFG Repo-Cleaner - 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.
| Criterion | Gitleaks 8.30.1 | Betterleaks 1.9.0 | TruffleHog 3.99.7 | Kingfisher 2.16.0 |
|---|---|---|---|---|
| Git repository and history | yes, gitleaks git (via git log -p) | yes, betterleaks git | yes, trufflehog git | yes, history included |
| Remote repository, organization | not documented (three modes: git, dir, stdin) | GitHub (organization, user, PRs, issues, Actions, releases), GitLab (group, project, merge requests), Hugging Face | GitHub (--org), GitLab, Hugging Face | GitHub, GitLab, Azure Repos, Bitbucket, Gitea, Hugging Face |
| Files and directories | yes, gitleaks dir | yes, betterleaks dir | yes, trufflehog filesystem | yes |
| Container image | not documented | not documented | yes, trufflehog docker | yes, kingfisher scan docker |
| Other sources | standard input | standard input, S3 (including Cloudflare R2) | S3, GCS, Postman, Jenkins, Elasticsearch, CircleCI, Travis CI, syslog, standard input | S3, GCS, Azure Blob Storage, Jira, Confluence, Slack, Teams, Postman |
| Checks that a secret is active | not documented | yes, 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, error | yes, 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 radius | not documented | not 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 types | yes, --blast-radius for the supported providers (identities, permissions, resources) |
| Revokes a secret | not documented | not documented in 1.9.0 (revocation only appears there as a status returned by validation); the version 2 preview announces betterleaks revoke | not documented | yes, kingfisher revoke, for the supported providers |
| Pre-commit hook | yes, pre-commit hooks provided | yes, pre-commit hooks provided | yes, documented (hooksPath, pre-commit framework, Husky) | yes, install script and pre-commit framework |
| CI integration | gitleaks-action action (separate repository), Docker image | Docker image ghcr.io/betterleaks/betterleaks; no dedicated action in the README | GitHub action trufflesecurity/trufflehog, Docker image | Docker image ghcr.io/mongodb/kingfisher; no dedicated action in the documentation |
| Output formats | JSON, CSV, JUnit, SARIF, template | JSON, CSV, JUnit, SARIF, template (JSONL for validate) | text, JSON, SARIF, GitHub Actions format | human-readable text, JSON, JSONL, BSON, TOON, SARIF, HTML |
| License | MIT | MIT | AGPL-3.0 | Apache-2.0 |
| Language | Go | Go | Go | Rust |
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
- TruffleHog tests whether each secret works, which sets inactive secrets aside from triage.
- 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...).
- It scans the whole history: all commits, all branches.
- The
verified,unknownandunverifiedstatuses are not handled the same way: onlyverifiedis certain, the other two call for a review. --results=verifiedkeeps only the active secrets: it is the basic triage option.- A pre-commit hook blocks secrets before they are committed.
- An exposed secret is a compromised secret: immediate rotation.
- 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.
- Official documentation: github.com/trufflesecurity/trufflehog
- List of detectors: trufflesecurity.com/detectors
- GitHub Action: marketplace/actions/trufflehog-oss
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
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
Review
(0/0)Score by domain
A domain groups several guides and gets several questions, so its score is more reliable than a per-topic score, which often rests on a single question.
Summary
Strengths
No topic passed at 80% on at least two questions yet.
Weak areas
No topic below the pass mark.
Recommended next
Hints before you try again?
Continue the course: Kingfisher: detect, validate and revoke a secret
A new full quiz with random questions
Work again only on the questions you missed