Pre-commit hook
The point of a pre-commit hook is to stop credentials from ever landing in your repo’s history. It runs locally, fast enough to feel synchronous, and blocks the commit if a finding shows up.
Install in one command
From inside a git repo:
keyhog hook install
That writes a .git/hooks/pre-commit script that calls
keyhog scan --fast --git-staged (the same command
.pre-commit-hooks.yaml exposes for the pre-commit framework).
If a pre-commit hook already exists in the repo, keyhog hook install refuses to overwrite it - remove it (or run
keyhog hook uninstall) and re-install. The next git commit
invokes the hook.
If your repo uses pre-commit instead of
raw git hooks, add the following to .pre-commit-config.yaml:
repos:
- repo: https://github.com/santhsecurity/keyhog
rev: v0.5.37
hooks:
- id: keyhog
stages: [pre-commit]
Then pre-commit install once, and it runs on every commit.
What gets scanned
keyhog scan --git-staged walks the index (the set of files git
is about to commit), not the working tree. Why this matters:
- A file you’ve modified but not
git added is NOT scanned. You’re free to keep credentials in scratch files as long as you don’t stage them. - A file you’ve staged then modified gets scanned in the staged
form, not the working-tree form. The scanner sees what
git commitwould commit.
The walk only includes files that are part of THIS commit, so it’s fast even on huge repos. A typical commit touches a few files and the scan is under 50 ms.
What happens on a finding
Stderr:
$ git commit -m "add staging config"
keyhog: 1 finding blocked this commit
src/config/staging.env:14:12 CRITICAL stripe-secret-key
sk_live_4eC39H...Tcd3Hc
Options:
1. Remove the credential from src/config/staging.env, then commit again.
2. Use a placeholder + load the real value from env at runtime.
3. If this is a false positive, run keyhog with --no-suppress-test-fixtures
or add to .keyhog.toml suppressions.
$
Exit code is 1, so git aborts the commit and your work-in-progress
stays in the index. Fix the file, git add the fix, and commit again.
When you really need to commit anyway
git commit --no-verify
That bypasses the hook. KeyHog logs nothing about it; that’s your
prerogative. Use it sparingly. A team norm of --no-verify for
“trust me” commits defeats the point of the hook.
A better pattern when a legitimate-looking credential needs to ship (e.g. a public OAuth client_id that vendor docs say to commit):
- Add its sha256 hash to
.keyhog.toml:[suppress] hashes = ["sha256:abc123..."] - Commit the suppression file alongside the credential.
- The next commit sees the hash and skips it.
This way the next contributor doesn’t have to learn the trick.
Performance
Pre-commit scans are designed for sub-100 ms latency on typical commits. If yours feels slow:
keyhog daemon start(unix only). The daemon holds the compiled scanner in memory; pre-commit invocations bypass the ~3 s cold start. Latency drops from ~3 s to ~30 ms.--fastskips the entropy / ML scorer. Removes ~20% of detectors but ~50% of scan time. Worth it for the pre-commit path; the full scan still runs in CI.
Uninstall
keyhog hook uninstall
Removes the KeyHog .git/hooks/pre-commit file if it carries the
generated KeyHog marker. If you hand-edited the hook,
keyhog hook uninstall refuses to touch it - clean it up by hand.
For the pre-commit framework, delete the keyhog stanza from
.pre-commit-config.yaml and run pre-commit clean.