Skip to content

feat: pluggable secret scanner interface (gitleaks, betterleaks, others) #208

@coopernetes

Description

@coopernetes

Goal

Secret scanning of in-flight pushes is a core proxy capability. The specific tool that does the scanning is an implementation detail — different scanners have different trade-offs (detection recall, binary size, rule sets, performance) and operators should be able to choose.

Extract a SecretScanner interface from the current GitleaksRunner implementation so scanners are swappable without touching the hook/filter chain.

Contract

interface SecretScanner {
    Optional<List<Finding>> scan(String diff, SecretScanConfig config);
    Optional<List<Finding>> scanGit(Path repoDir, String commitFrom, String commitTo, SecretScanConfig config);
}

Both methods follow the existing fail-open contract: Optional.empty() means the scanner was unavailable or errored; Optional.of(list) means the scanner ran (list may be empty for a clean result).

Candidate implementations

Scanner Binary size Notes
gitleaks (current) ~21MB (8.30.1) Stable, well-known; grew significantly in recent releases
betterleaks ~40MB (v1.1.2, down from 51MB) Higher recall (98.6% vs 70.4%), 4–5× faster; CLI subcommand structure differs from gitleaks — needs adapter work

What needs doing

  1. Extract SecretScanner interface from GitleaksRunner
  2. Rename GitleaksRunnerGitleaksScanner implements SecretScanner
  3. Add commit.secretScanning.engine config key (default: gitleaks)
  4. Wire selected implementation through SecretScanConfig or a scanner factory
  5. When betterleaks CLI is stable enough: add BetterleaksScanner implementation and verify the same tests pass

Notes on betterleaks CLI compatibility (needs verification before point 5)

  • detect --pipestdin subcommand (reads unified diff from stdin)
  • git --log-opts=<range> semantics need confirming
  • Exit code for findings must be configurable to match our FINDINGS_EXIT_CODE = 2 assumption
  • Binary size is trending down; worth re-evaluating when it approaches gitleaks parity

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions