#2129·gitleaks

`gitleaks git` silently reports "no leaks found" with exit 0 when `git log` writes anything to stderr (git-crypt repos affected by default)

Author: iam6ft7inCreated May 22, 2026Updated Sep 15, 2026

Summary

gitleaks git treats any output on git log's stderr as a fatal abort, then prints 0 commits scanned, no leaks found, and exits 0. This is a silent false negative: a user running gitleaks git in CI or at the command line sees a clean report when in fact nothing was scanned.

This is the same class of issue as #1450 (invalid --log-opts) and #1455 (broken repo), but it bites a much broader population: any repository that uses git-crypt triggers it by default, with no misconfiguration on the user's part. The git-crypt diff.textconv filter writes a multi-line Warning: file not encrypted to stderr for every historical commit that touches a now-encrypted path. That's enough to abort gitleaks git.

Versions

  • gitleaks v8.30.1 (latest as of 2026-05-21)
  • git-crypt 0.7.0 (relevant only as a stderr source)
  • Reproduced on Windows 11 with Git for Windows 2.x

Reproduction

In any git-crypt repo with at least one encrypted-path commit in history:

bash
gitleaks git

Observed output (truncated):

ERR [git] git-crypt: Warning: file not encrypted
ERR [git] git-crypt: Run 'git-crypt status' to make sure ...
... (repeated per commit) ...
ERR  error="stderr is not empty"
INF 0 commits scanned.
INF scanned ~2622506 bytes (2.62 MB) in 2.22s
INF no leaks found
$ echo $?
0

Note the 0 commits scanned and the 0 exit code. A user who only reads the final no leaks found line believes the repo is clean.

Workaround (works, but should not be necessary)

bash
git log -p --all 2>/dev/null | gitleaks stdin

This bypasses gitleaks' internal git log invocation and discards stderr, producing a real scan (~2.81 MB vs ~2.62 MB on the broken path in our repo; commits scanned is no longer surfaced because stdin doesn't track that, but the diff stream is fully consumed).

Suggested fixes (any one would close the silent-false-negative class)

  1. When git log -p produces no commits and stderr is non-empty, exit non-zero (configurable via --exit-code already, but it isn't honored in this path).
  2. Make error="stderr is not empty" a hard error by default, with an opt-in --allow-git-stderr flag for users who knowingly run in noisy contexts (git-crypt, hooks, custom textconv filters).
  3. Distinguish "git log spoke to stderr while still streaming commits" (warning) from "git log spoke to stderr and produced zero commits" (fatal).

The current behavior conflates a security-relevant zero-commits-scanned condition with a successful clean scan. Either of the first two options would fix that without breaking the noisy-stderr-but-still-scanning case.

Related issues

  • #1450: Invalid --log-opts disregards git log exit code and silently does nothing at all
  • #1455: Scan for broken git repo

This issue is narrower than either of those in that the trigger is a common, non-broken configuration (git-crypt is widely used for repo-versioned secrets), but the underlying defect is the same: stderr-driven abort + exit 0

  • "no leaks found".

Why this matters

git-crypt is one of the standard answers to "how do I version-control secrets in a private repo?" Running gitleaks git on such a repo is a routine defense-in-depth step. A silent false negative here is exactly the threat model gitleaks exists to defend against.