A secret scanner for the three places credentials actually hide: old git commits, Docker image layers, and your working tree. Regex for the keys you can name, Shannon entropy for the ones you can't.
The problem
You committed a key, noticed, and moved it to an environment variable. The file looks fine now. But git kept the old version, and anyone who clones the repo gets the whole history.
Three sources
Walks every commit on every branch and scans the added lines of each diff — not just the files you have checked out today.
Recurses a directory tree, skips node_modules and binaries, and scans each text file line by line.
Unpacks a docker save tarball and scans inside each layer — including a key baked into an early layer and "removed" later.
How detection works
Regex catches secrets with a recognisable shape. Entropy catches the shapeless rest. You need both.
High-signal patterns anchored to provider-specific prefixes, so they rarely fire on ordinary text. An AWS key starts with AKIA; a GitHub token with ghp_.
No regex matches a random 40-character secret with no prefix. So measure its randomness instead — bits per character:
Flag base64 runs above 4.5 and hex runs above 3.0 bits/char. Try it on real strings:
The pipeline
Drop-in for CI
No config, no server, no parsing. Findings fail the build. Add it to a pipeline or a pre-commit hook in one line.
# fail the build if any secret is in the history - name: Scan for secrets run: | go install github.com/SpenceChakabva/shhscan@latest shhscan git . # exits 1 on a finding → build fails
Honest limitations
Rebuilding a scanner from scratch — instead of running gitleaks — was the point. You only understand a detector's blind spots once you've written one.
shhscan says a string looks like a secret. trufflehog goes further and calls the provider to check it's still live. That's the higher bar — and the obvious next iteration.
Randomness flags real secrets and every UUID and content hash alike. The allowlist does the real work; newer tools are already moving past raw Shannon entropy.
A key split across lines or built at runtime from concatenated strings walks straight past a line scanner. Knowing that is the difference between a control and theatre.