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

Betterleaks: detect secrets, then check whether they are still active

By updated

Improve this page

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.0Version 2.0.0
Statuslatest stable, from 29 September 2026preview, rc.5 from 28 October 2026
Scan a directorybetterleaks 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 configurationdiscovered in the target directory--config only
JSON reportoriginal schemanew envelope and new result schema
Go modulegithub.com/betterleaks/betterleaksgithub.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.

Terminal window
docker pull ghcr.io/betterleaks/betterleaks:v1.9.0@sha256:e3b95b0db6c2735db17165c009b0ad6d9cef34fb4578659232b98f69d7346cac

The 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.

Terminal window
# A directory or a file; "file" and "directory" are aliases of "dir"
betterleaks dir /path/to/target
# A local Git repository, history included
betterleaks git /path/to/repo
# Standard input
cat file.txt | betterleaks stdin

In 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 110ms
WRN leaks found: 1

Read 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.

Terminal window
# A GitHub organisation, widened to issues and pull requests
betterleaks github https://github.com/mon-organisation --include issues,prs
# A GitLab project and its CI jobs
betterleaks gitlab https://gitlab.com/mon-groupe/mon-projet --include issues,mrs,ci-jobs

Detection, 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.

  1. 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.

  2. Validation queries the provider

    In v1, --validation asks the provider whether the token found is still valid; in v2, it is -v or --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.

  3. 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.

Terminal window
# Which rules can analyse, and which can revoke (v2)
betterleaks config show ids --analysis
betterleaks 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 expensive
prefilter = '''
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 match
filter = '''
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.

Terminal window
betterleaks dir . --config .betterleaks.toml --redact --report-format sarif --report-path resultats.sarif

The --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.

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 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 --validation in v1, -v in 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, -v means --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 latest tag does not point to the latest stable, and the v2 tag 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

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

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.

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