A zero-dependency pre-commit hook that blocks secrets before they enter git history.
Reason this release was yanked:
0.1.2 includes security fixes. Previous version had regressions; please upgrade.
Project description
git-secret-guard
A zero-dependency pre-commit hook that blocks secrets before they enter git history.
Designed to be loud, fast, and boring:
- Loud. When a secret matches, the commit stops. No silent partial scans.
- Fast. Pure regex over
git diff --cached; finishes in milliseconds on normal diffs. - Boring. No network calls, no ML, no hidden state. One regex per rule, each with positive and negative tests. Catalog is append-only; rule IDs never change meaning.
Why another secret scanner? Most existing tools run as a repo-wide scan on
a schedule or in CI. By then the secret is already committed, already pushed,
and already indexed. git-secret-guard runs before the commit lands, so
the credential never enters history at all.
Install
pip install git-secret-guard
Or use pipx so the CLI lands on your PATH without polluting the project's environment:
pipx install git-secret-guard
Use it with pre-commit.com
Add to .pre-commit-config.yaml:
repos:
- repo: https://github.com/hinanohart/git-secret-guard
rev: v0.1.0
hooks:
- id: git-secret-guard
Then:
pre-commit install
Use it without pre-commit.com
pip install git-secret-guard
git-secret-guard install-hook
This drops a 3-line .git/hooks/pre-commit wrapper that calls
git-secret-guard scan. Use --force to overwrite an existing hook.
What it catches
| Category | Example rule | Default severity |
|---|---|---|
| Filenames | .env, id_rsa, .aws/credentials, .netrc, .pypirc |
BLOCK |
| Cloud | AWS access/secret keys, Azure storage connection strings, GCP service-account JSON | BLOCK |
| VCS | GitHub PATs (classic + fine-grained), GitHub OAuth tokens, GitLab PATs | BLOCK |
| Chat | Slack tokens, Slack/Discord webhooks, Telegram bot tokens | BLOCK |
| SaaS | Stripe, SendGrid, Mailgun, OpenAI, Anthropic, Google API keys | BLOCK |
| Cryptographic | PEM private-key headers, PGP private-key blocks, JWTs | BLOCK (WARN for JWT) |
| Generic | api_key = "..." style literal assignments |
WARN |
See docs/PATTERNS.md for every rule, its ID, regex, and
rationale.
Configure
Config lives at ~/.config/git-secret-guard/config.toml, or
.git-secret-guard.toml at the repo root, or wherever
$GIT_SECRET_GUARD_CONFIG points.
# Silence specific rules by their stable ID. Everything else keeps working.
allowlist = [
"filename-credentials-json",
]
# Never block — just print findings. Good for onboarding.
dry_run = false
# Treat WARN as BLOCK. Good for teams that want zero tolerance.
warn_as_block = false
Inline allow pragma
For one-off false positives (e.g. a test fixture with a dummy JWT), put the pragma on the same line as the match:
TOKEN = "eyJhbGci..." # git-secret-guard: allow jwt-token
Multiple rule IDs can be comma-separated: # git-secret-guard: allow r1, r2.
The pragma only silences the line it's on — it cannot be used at the top of
a file to disable scanning wholesale.
CLI
git-secret-guard scan # scan staged files (exit 1 on BLOCK)
git-secret-guard scan --dry-run # never exit non-zero
git-secret-guard scan --json # machine-readable output
git-secret-guard scan --all-files PATH... # scan working tree instead of diff
git-secret-guard install-hook # write .git/hooks/pre-commit wrapper
git-secret-guard list-rules # print the catalog
git-secret-guard version
Library API
from git_secret_guard import scan_staged, Outcome
decision = scan_staged()
if decision.outcome is Outcome.BLOCK:
for f in decision.findings:
print(f.rule_id, f.path, f.line, f.reason)
Every dataclass is frozen and JSON-safe via .to_dict().
Design commitments
- Tight regexes over fuzzy ones. A rule that fires weekly on legitimate code gets ignored; an ignored rule is worse than no rule. We prefer to miss an exotic-looking secret rather than block a valid commit.
- Stable rule IDs. Pinning an ID in your allowlist must keep working across minor versions. New coverage is added as new IDs.
- No network, no telemetry. The scanner doesn't call home. Your diffs stay on your machine.
- Fail open on git errors. If
gititself is broken, the hook exits 0 and logs a warning. A broken guard must not become a second outage.
Threat model
git-secret-guard is a speed bump, not a vault.
- In scope: hard-coded credentials typed or pasted into source files that get committed — the single most common source of real-world credential leaks.
- Out of scope: deliberately obfuscated secrets (base64 encoding, string
slicing), secrets in binary blobs, secrets that the rule catalog hasn't
learned about yet, and attackers with push access who can
--no-verify. For those, combine this with server-side scanning, short-lived credentials, and least-privilege IAM.
If a secret ever does land in a commit, rotate it immediately — even if you delete the commit. Assume anything ever pushed to a public host is compromised.
Contributing
New rule? See CONTRIBUTING.md. Every rule must ship
with positive and negative tests and a one-sentence rationale.
Found a real-world secret shape we miss? Open an issue — please scrub the value first.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file git_secret_guard-0.1.0.tar.gz.
File metadata
- Download URL: git_secret_guard-0.1.0.tar.gz
- Upload date:
- Size: 34.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
931407fccdf62254460d9ae1c831fb22ff9f40f80b96076f2e5e6c1aa398582c
|
|
| MD5 |
09168633928853e4523c6bc5b60139a8
|
|
| BLAKE2b-256 |
9e83c01d3da526a3dfc02b7aa1f422600b6591f7e4699a73592012b3efd21ea6
|
Provenance
The following attestation bundles were made for git_secret_guard-0.1.0.tar.gz:
Publisher:
release.yml on hinanohart/git-secret-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_secret_guard-0.1.0.tar.gz -
Subject digest:
931407fccdf62254460d9ae1c831fb22ff9f40f80b96076f2e5e6c1aa398582c - Sigstore transparency entry: 1329907384
- Sigstore integration time:
-
Permalink:
hinanohart/git-secret-guard@3a0903df16368d303b10cb63d5711dd0526d4094 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/hinanohart
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3a0903df16368d303b10cb63d5711dd0526d4094 -
Trigger Event:
push
-
Statement type:
File details
Details for the file git_secret_guard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: git_secret_guard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
911de78ceaff6e347c346842dfe1376e0b7ac48fb5abb669af4359526a5689d2
|
|
| MD5 |
521e71c319209d7023f6440779c8cf92
|
|
| BLAKE2b-256 |
c17422c40186719de4c2e9edbf40b44d303f20b1dfa4081c871cbad452fc68de
|
Provenance
The following attestation bundles were made for git_secret_guard-0.1.0-py3-none-any.whl:
Publisher:
release.yml on hinanohart/git-secret-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_secret_guard-0.1.0-py3-none-any.whl -
Subject digest:
911de78ceaff6e347c346842dfe1376e0b7ac48fb5abb669af4359526a5689d2 - Sigstore transparency entry: 1329907436
- Sigstore integration time:
-
Permalink:
hinanohart/git-secret-guard@3a0903df16368d303b10cb63d5711dd0526d4094 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/hinanohart
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3a0903df16368d303b10cb63d5711dd0526d4094 -
Trigger Event:
push
-
Statement type: