Whac-a-Leak logo: a Go gopher at a whack-a-mole cabinet operates a robot with mallets. Keys, a padlock, a certificate, an API key, a token, a password and a .env file come out of the holes.
> whac_

Find secrets before they leak

Whac-a-Leak is a secret scanner in pure Go. CUE defines its rules. Each rule has a type, organization layers and its own samples. If a sample fails, whac does not load the rules. The engine checks keywords first, then regex and entropy. It reads YAML, JSON and .env files as key paths.

Get StartedDesign DecisionsGitHub →
go install github.com/infrashift/whac-a-leak/cmd/whac@v0.1.0Release v0.1.0: archives for Linux and macOS (amd64, arm64), with checksums and build provenance. Apache 2.0. Download · Install guide
.whac/acme.cue  ·  a rule with its own samples
package whac

// A rule for a fictional provider. Each rule has samples.
// whac stops the load if a sample gives the wrong result.
rules: ACME_API_TOKEN: {
	description: "Acme API token"
	severity:    "CRITICAL"
	keywords: ["acme_"]
	regex: #"\b(acme_[A-Za-z0-9]{32})\b"#
	entropy: {min: 3.5, charset: "alnum"}
	tests: {
		mustMatch: ["token = acme_EXAMPLE0123456789abcdefghijklmno"]
		// Matches the regex but fails the entropy check: not a secret.
		mustIgnore: ["token = acme_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"]
	}
}
whac scan app.env  ·  findings
CRITICAL  ACME_API_TOKEN  app.env:2:12
          Acme API token
          secret: acme****lmno
          fingerprint: whac1:570a9c2746d48b53c51a70dda018e064e5885c1d6fe16abf63fb7a28d24359b9

CRITICAL  GITHUB_TOKEN  app.env:4:10
          GitHub personal access, OAuth, app or refresh token
          secret: ghp_****oPqr
          fingerprint: whac1:ceaecd45ce7e62d41df233cda112cf1e4aed182b36f61607fec15d2826878fec

2 finding(s): 2 CRITICAL. Scanned 1 file(s), 187 B.

Left: a layer with one rule. Right: the output of whac scan on a file with fake tokens. The placeholder token is not reported. whac produced this output.

Why Whac-a-Leak?

✅

Rule Samples

Each rule has mustMatch and mustIgnore samples. The engine runs them at every load. If a sample fails, whac does not load the rules.

🧱

Organization Layers

The binary contains the builtin rules. Layers in your .whac/ config dir add rules, tighten rules, and disable or re-grade rules by ID. No fork is necessary.

⚡

Two-Tier Engine

One Aho-Corasick pass selects the candidate rules. Only those rules run their regex and entropy checks. Pure Go, CGO_ENABLED=0, one static binary.

🗂

Structured Files

whac reads YAML, JSON, .env, properties and HCL-style files as key paths. It finds a password at database.credentials.password with low entropy and no prefix.

🔑

Fingerprint Allowlists

A whac1: fingerprint of the rule and the secret identifies each finding. It contains no file or line, so allowlist entries survive rebases.

🔎

Files, History, Agents

Scan a directory, staged changes or the full git history. Audit the environment variables and credential files of an agent before it starts. Output: text, JSON or SARIF. No network calls.

Where it's headed

The project wiki tracks each milestone as an issue. Each milestone lands as one tested commit.

CUE rulesSchema, layering, rules verify
Done
Scan enginePrefilter, entropy, fingerprints
Done
Structure-awareYAML · JSON · .env key paths
Done
GitPre-commit and full history
Done
ReleaseSARIF, default rules, CI
Done
Agent preflightEnv vars, SSO caches, sockets
Done

Each rule passes its samples before it runs

The rules set the quality of a secret scanner. whac does not load a rule that fails its own samples.

Get StartedDesign Decisions