Skip to content

feat!: migrate secret-scan from gitleaks to betterleaks - #70

Merged
nkg merged 1 commit into
mainfrom
feat/betterleaks-migration
Aug 30, 2026
Merged

feat!: migrate secret-scan from gitleaks to betterleaks#70
nkg merged 1 commit into
mainfrom
feat/betterleaks-migration

Conversation

@nkg

@nkg nkg commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Why

betterleaks is gitleaks' successor, written from scratch by gitleaks' original author (Zach Rice) after he lost admin control of that repository and its name. It's MIT, he retains ownership, and it carries no license key requirement for org use — which is the same reason secret-scan.yml installed the OSS gitleaks binary rather than the paid official gitleaks-action.

BREAKING

The gitleaks-version input is replaced by betterleaks-version (default 1.8.1). A caller still passing gitleaks-version will fail validation.

Per the repo's precedent for breaking input changes, this bumps the major — docs move to @v3. release.yml derives the floating tag generically (v1.2.3v1), so a v3.0.0 tag creates v3 with no change needed there.

Compatibility

Verified against the actual v1.8.1 binary, not the docs:

  • Every flag used here exists: --no-banner, --redact, --report-format=sarif, --report-path, --config, --exit-code, --log-opts, and git --staged --pre-commit
  • Release tarballs are named identically in shape; both linux arches download and contain a top-level betterleaks binary (static ELF) — install step verified end-to-end
  • Still reads .gitleaks.toml, GITLEAKS_CONFIG, .gitleaksignore (same fingerprint format) and gitleaks:allow comments as fallbacks, so existing consumer configs need no changes
  • mise registry already carries betterleaks (via aqua, with cosign verification on install)
  • Renovate keeps working: datasource=github-releases depName=betterleaks/betterleaks

Expect new findings

betterleaks reports ~98.6% recall on CredData vs gitleaks' ~70.4%. A repo that scanned clean may not any more. This repo was exactly that case:

scanner full-history result exit
gitleaks 8.30.1 no leaks found 0
betterleaks 1.8.1 leaks found: 1 1

The finding is a false positive — GRAFANA_ADMIN_PASSWORD=ci-validate, a documentation placeholder in examples/README.md:159 at commit 526db3a, matched by generic-password at low confidence.

Because such matches live in committed history, a betterleaks:allow comment on the current line can't clear them — the fingerprint has to be pinned. Hence the new .gitleaksignore. Note PR-diff mode is unaffected unless the offending line is touched, so this surprise lands on push/scheduled full-history runs, not on PRs.

Consumers hitting the same thing have two options, both verified:

  • pin fingerprints in .gitleaksignore (preferred — keeps low-confidence detection on)
  • set the new confidence: medium input (blunter; drops a whole tier)

Also changed

  • mise.toml + lefthook.yml — local pre-commit/pre-push secret scans use betterleaks, so mise install on an existing clone swaps the binary
  • SARIF artifact renamed gitleaks-sarifbetterleaks-sarif

Test plan

  • actionlint clean
  • yamllint .github/ .yamllint.yml clean (only pre-existing line-length warnings in claude-code-review.yml)
  • Full-history scan green with .gitleaksignore (betterleaks git --redact --no-banner → exit 0)
  • Staged/pre-commit mode green
  • PR-diff mode (--log-opts=base..head) runs and writes SARIF
  • Install step verified against both linux_x64 and linux_arm64 tarballs
  • All pre-push hooks green

Not done

Betterleaks ships checksums.txt + a sigstore bundle and the install step still verifies nothing. Left out to keep this diff to the migration — worth a follow-up.

🤖 Generated with Claude Code

https://claude.ai/code/session_011c5RTvAwJB62bcvuARUqKr

betterleaks is gitleaks' successor, written from scratch by gitleaks'
original author after he lost admin control of that repo and its name.
MIT, no license key for org use — the same reason this workflow installed
the OSS gitleaks binary rather than the paid official action.

BREAKING: the `gitleaks-version` input is replaced by `betterleaks-version`.

Compatibility is near-total, which is what made the swap cheap. Verified
against the v1.8.1 binary rather than the docs: every flag used here exists
(--no-banner, --redact, --report-format=sarif, --report-path, --config,
--exit-code, --log-opts, git --staged/--pre-commit), release tarballs are
named identically in shape and contain a top-level binary on both linux
arches, and .gitleaks.toml / GITLEAKS_CONFIG / .gitleaksignore (same
fingerprint format) / `gitleaks:allow` are all still honoured as fallbacks.

Expect new findings: ~98.6% recall on CredData vs gitleaks' ~70.4%. This
repo was exactly that case — full history went from "no leaks" to 1 leak,
a low-confidence generic-password match on the GRAFANA_ADMIN_PASSWORD
placeholder in examples/README.md. Such matches live in committed history,
so an allow-comment can't clear them; .gitleaksignore pins the fingerprint.
Adds a `confidence` input as the blunter escape hatch for consumers.

Local tooling moves too (mise.toml, lefthook.yml), and the docs move to @V3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c5RTvAwJB62bcvuARUqKr
@nkg
nkg merged commit c5d35aa into main Aug 30, 2026
11 checks passed
@nkg
nkg deleted the feat/betterleaks-migration branch August 30, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant