Betterleaks is a secrets scanner written by the Gitleaks team, and it goes further than detection: it can check whether the secret it found is still active. That is the difference that matters in practice, because a classic scan returns a list of candidates without saying which ones are dangerous today. The project is MIT-licensed, written in Go, and its development is backed by Aikido Security.
What you will learn
- Place Betterleaks against Gitleaks, now frozen, and against TruffleHog.
- Choose between the stable version 1 and the version 2 preview, which have neither the same interface nor the same installation channels.
- Install the tool and run a first scan on a Git repository.
- Tell apart detection, validation and analysis, three steps that do not have the same cost or the same side effects.
- Reduce false positives with Expr expressions, which the tool evaluates before and after the pattern search.
- 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.
Why a successor to Gitleaks
Gitleaks is still usable, and its README declares it functionally frozen: its author no longer merges features and only publishes security fixes. For a secrets scanner, this freeze has a direct consequence that the Gitleaks guide details: the detection rules stop growing, while new token formats appear regularly.
Betterleaks therefore covers the same ground with a team that includes the original author. The repository was created on 3 February 2026, it is not archived, and its latest stable version, 1.9.0, dates from 29 September 2026. This is not a fork abandoned in a corner: development is active, with five 2.0.0 previews published between 30 September and 28 October 2026.
Two versions, two interfaces
This is the point to settle before installing anything, because a good part of the documentation online describes a version that is not yet stable. The main branch of the repository carries the development of v2, while the maintenance of v1 lives on the v1.x branch.
| Version 1.9.0 | Version 2.0.0 | |
|---|---|---|
| Status | latest stable, from 29 September 2026 | preview, rc.5 from 28 October 2026 |
| Scan a directory | betterleaks dir <path> | betterleaks fs <path>, or the path alone |
| Validate secrets | --validation | -v, or --validate |
Meaning of -v | --verbose, detailed output | --validate, calls to the providers |
| Local configuration | discovered in the target directory | --config only |
| JSON report | original schema | new envelope and new result schema |
| Go module | github.com/betterleaks/betterleaks | github.com/betterleaks/betterleaks/v2 |
The -v flag changes meaning from one version to the other, and it is a migration trap. In v1, it stands for --verbose and merely enriches the output. In v2, it stands for --validate and triggers calls to the token providers. A command copied as is after a version upgrade can therefore send your secrets to third-party APIs, with nothing to announce it. Both meanings were read in the source code of each branch.
Installation
Choose your channel according to the version you are aiming for. The package managers follow v1 until 2.0.0 is stable, which is the expected behaviour and not a packaging delay.
The image carries its digest: a bare tag can be moved to other content without anything signalling it.
docker pull ghcr.io/betterleaks/betterleaks:v1.9.0@sha256:e3b95b0db6c2735db17165c009b0ad6d9cef34fb4578659232b98f69d7346cacThe preview is named in full, since it updates neither latest, nor v2, nor the Homebrew cask.
docker pull ghcr.io/betterleaks/betterleaks:v2.0.0-rc.5@sha256:35f0b9cfb194d5a84000ceb91085d8a42098bedb4f7e65938fd73f02daa63d54Installing with Go compiles from source and lets you choose the exact version; for version 2, the module path carries the /v2 suffix.
# Version 2 previewgo install github.com/betterleaks/betterleaks/v2@v2.0.0-rc.5These channels serve v1 until the stable release of 2.0.0.
# macOSbrew install betterleaks
# Fedorasudo dnf install betterleaksThe first scans
Each source is named explicitly, and v1 has no default command: a path given alone scans nothing. The ergonomics stay close to those of Gitleaks, which limits the cost of switching for simple uses.
# A directory or a file; "file" and "directory" are aliases of "dir"betterleaks dir /path/to/target
# A local Git repository, history includedbetterleaks git /path/to/repo
# Standard inputcat file.txt | betterleaks stdinIn version 2, the dir command is called fs, with filesystem as its long form, and the path can do without a subcommand. This is the most visible difference between the two interfaces, and the first one to fix in a script reused as is. In 1.9.0, betterleaks fs answers unknown command "fs", and a path given alone gets the same answer.
The output of a scan fits on two lines. Here is the one obtained on a test file that contains a fake GitHub token:
INF scanned ~119 bytes (119 bytes) in 110msWRN leaks found: 1Read the first line before rejoicing over an empty report: a scanned volume unrelated to the size of the target signals a scan that did not see what you thought, for example a truncated clone in CI or a wrong starting path.
Beyond the repository, Betterleaks can query sources that Gitleaks does not cover: a GitHub or GitLab organisation with its issues and its pull or merge requests, a Hugging Face space, an S3 bucket. This is useful when the secret does not leak through the code, but through a comment on an issue.
Version 2, in preview, adds the container image to these, with its historical layers and its attestations. This source does not exist in version 1: there is no point looking for it in the subcommand list of the stable branch.
# A GitHub organisation, widened to issues and pull requestsbetterleaks github https://github.com/mon-organisation --include issues,prs
# A GitLab project and its CI jobsbetterleaks gitlab https://gitlab.com/mon-groupe/mon-projet --include issues,mrs,ci-jobsDetection, validation, analysis
These three words designate three different steps, and mixing them up leads to sending secrets to third-party APIs without having decided to.
-
Detection stays local
The scan looks for patterns, applies its filters and returns results, with no request at all to the token providers. This is the default behaviour in both versions.
-
Validation queries the provider
In v1,
--validationasks the provider whether the token found is still valid; in v2, it is-vor--validate. Triage benefits: a key revoked six months ago does not deserve the same urgency as an active token. The price to pay is real too, since the secret leaves your machine. -
Analysis resolves identity and permissions
v2 adds
-a, or--analyze, which enriches valid tokens with the account they belong to, their capabilities and a severity. Analysis implies validation, it does not replace it.
In version 2, the BETTERLEAKS_VALIDATE and BETTERLEAKS_ANALYZE environment variables enable these steps without touching the commands, and an explicit option takes precedence over the variable. In CI, prefer the option: a variable set at the level of an entire project ends up applying to pipelines that were not expecting it.
Version 2 can also revoke a secret, when the rule defines that action. This is a separate operation: no scan triggers it, it is launched deliberately.
# Which rules can analyse, and which can revoke (v2)betterleaks config show ids --analysisbetterleaks config show ids --revocation
# Revoke explicitly, outside of any scan (v2)betterleaks revoke --rule <rule-id>Filtering false positives with Expr
This is the tool's advertised strength, and the reason why its configuration looks little like that of Gitleaks. Filters are written in Expr, an expression language, and take effect at two distinct moments.
A prefilter is evaluated before any pattern search. It only sees the attributes of the resource, such as the file path or the commit author, and is used to discard early what is not worth scanning. A filter is evaluated after a match, and additionally sees the candidate result, hence the secret itself and the text around it.
# Discard whole paths before the search, which is expensiveprefilter = '''matchesAny(attributes["path"], [ `(?i)\.(?:bmp|gif|jpe?g|png|svg|tiff|pdf|exe)$`, `(?:^|/)node_modules(?:/.*)?$`, `(?:^|/)vendor(?:/.*)?$`])|| attributes["git.author_name"] == "renovate[bot]"'''
# Discard sample values, after a matchfilter = '''containsAny(finding["secret"], [ "EXAMPLE", "CHANGEME", "YOUR_API_KEY_HERE", "0000000000000000"])'''The distinction has a direct effect on the scan duration. A prefilter that discards node_modules avoids reading thousands of files; an equivalent filter would have read them all before throwing the results away. On a large repository, this can separate a tolerable merge request scan from a scan that ends up disabled.
The tool also offers a so-called BPE filtering, which measures how "rare" a string is with regard to natural language. The idea is to discard ordinary sentences that a generic detector takes for high-entropy secrets. Check its effect on your repositories before relying on it: a statistical filter has to be tuned to the corpus it processes.
Integrating Betterleaks into a pipeline
v1.9.0 picks its configuration according to a four-level order of precedence, which its help documents: the --config option first, then the BETTERLEAKS_CONFIG or GITLEAKS_CONFIG variables, then the same ones suffixed _TOML, which carry the content, and finally a .betterleaks.toml or .gitleaks.toml found in the target directory. With none of these, the tool applies its built-in configuration.
This last level is convenient and risky: simply running the scan from another directory changes the rules without you noticing. In CI, name the configuration explicitly.
betterleaks dir . --config .betterleaks.toml --redact --report-format sarif --report-path resultats.sarifThe --redact option masks the value of the secret in the report, and it accepts a percentage: --redact=20 masks only part of it, while no value masks everything. This is valuable as soon as the report becomes a CI artifact, which a whole team can read. A scan returns exit code 1 when it finds something, and --exit-code changes that value if your platform expects another one.
Before wiring it all in, betterleaks config check compiles the configuration without contacting any provider, and betterleaks config path tells you which source was retained, which settles the doubt in one command.
Two framings are worth more than a single scan, and the guide on secrets scanning develops this logic. The merge request scan covers a diff and must stay fast. The scheduled scan goes over the full history again and catches what yesterday's rules could not detect, which is precisely the argument in favour of a tool that is still being developed.
Taking over a Gitleaks configuration
Version 1 of Betterleaks eases the takeover of an existing Gitleaks setup: it reads a .gitleaks.toml like a .betterleaks.toml, --gitleaks-ignore-path accepts a .gitleaksignore, and --ignore-gitleaks-allow handles gitleaks:allow comments the same way as betterleaks:allow. The takeover is still not a binary swap: the filtering logic is written in Expr, and nothing guarantees equivalent results, as the box below shows.
The same test shows what a poorly chosen configuration costs. Run with the built-in configuration, the scan returns leaks found: 1 and exits with 1. Run with a configuration file that declares no rule, it returns no leaks found and exits with 0, on exactly the same file. A green pipeline therefore tells you nothing until you have checked which configuration was loaded.
Gitleaks, Betterleaks, TruffleHog or Kingfisher: which one should you choose?
Betterleaks comes from the Gitleaks team and adds rules that can be filtered in Expr, optional validation and new sources. The table places it among the three other scanners of the module, including TruffleHog for verification and Kingfisher for 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 takeaways
- Betterleaks is developed by the Gitleaks team, under the MIT licence, with the backing of Aikido Security.
- Gitleaks is functionally frozen and only receives security fixes, which freezes its detection rules.
- 1.9.0 is the latest stable version; 2.0.0 remains a preview, with a different interface and report format.
- A scan contacts no provider by default: validation is enabled with
--validationin v1,-vin v2, and it makes the secret leave your machine. - Expr filters run before or after the pattern search, and this choice decides the scan duration as much as its accuracy.
- In v1,
-vmeans--verbose; in v2, it means--validate: the same flag displays details or calls the providers depending on the version. - The configuration is chosen by an order of precedence whose last level is the target directory: running the scan elsewhere changes the rules without warning.
- The
latesttag does not point to the latest stable, and thev2tag does not exist yet: name the version and pin by digest. - For the SOCLE-SEC-GEN-6 requirement, the expected evidence is a detection system, here a Betterleaks 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.
Knowledge check
Check that you have the essentials of this lesson. 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: TruffleHog: detect secrets exposed in your code and infrastructure
A new full quiz with random questions
Work again only on the questions you missed
Resources
The links below point to the official sources of the project. The v1.x branch carries the stable version documented here, while main already describes version 2: reading the wrong branch leads to wrong command names.
- Repository: github.com/betterleaks/betterleaks
- Version 1 branch: v1.x
- Migration guide to version 2: docs/v2_migration.md
- Filter language: expr-lang.org