credguard
Stop credentials from ever reaching your git history. credguard scans staged
content before a commit lands, blocks the commit when it finds a token,
password, key or connection string, and tells you what to do about it.
- 38 provider rules — AWS, GitHub, GitLab, Slack, Stripe, OpenAI, Anthropic, Google, Azure, npm, PyPI, SendGrid, Twilio, Shopify, Discord, Telegram, Databricks, Hugging Face, private keys, DB URIs, auth headers, payment cards.
- Checksum verification where the provider supports it (GitHub CRC32,
card issuer prefix + Luhn). A verified match is escalated to
CRITICAL. - Entropy heuristic for keys no pattern covers, tuned to stay quiet on hashes, UUIDs, lockfiles and charset constants.
- Scans the index, not the working tree — what you're actually committing.
- Zero runtime dependencies on Python 3.11+ (
tomlionly below that). - Secrets are never echoed. Output, JSON, SARIF and the baseline file all carry masked values and fingerprints only.
Install
pip install credguard # from PyPI once published
pip install -e . # from this source tree
Quick start
credguard install-hook # blocks commits (.git/hooks/pre-commit)
credguard install-hook --type pre-push # blocks pushes as well
credguard scan # scan the working tree
credguard scan --staged # scan what is staged (what the hook runs)
credguard scan --range main..HEAD # scan lines added in a range (CI)
credguard rules # list every rule and its severity
Exit codes: 0 clean, 1 blocking findings, 2 usage/config error.
With pre-commit
# .pre-commit-config.yaml
repos:
- repo: https://github.com/your-org/credguard
rev: v0.1.0
hooks:
- id: credguard
In GitHub Actions
- run: pip install credguard
- run: credguard scan --range "${{ github.event.pull_request.base.sha }}..HEAD" --format github
Use --format sarif --output credguard.sarif to feed GitHub code scanning.
Adopting it on a repo that already has findings
Record what exists today so only new secrets fail the build:
credguard baseline # writes .credguard-baseline.json
git add .credguard-baseline.json
The baseline stores sha256(path + rule + secret) fingerprints and masked
values — no plaintext. Fingerprints survive line moves and reformatting.
credguard prune-baseline lists entries that no longer match anything.
A baselined secret is still a leaked secret. Rotate it; the baseline only stops the check from failing repeatedly while you work through the list.
Suppressing a false positive
Narrowest option first:
API_URL = "https://api.example.com/v3/aBcDeF0123456789" # credguard:ignore
KEY = "Kq7zP2mXv9Ld4RbT" # credguard:ignore[high_entropy_string]
# credguard:ignore-next-line
SAMPLE = "sk_live_51H8bQwKZvKQ1aBcDeFgHiJkL"
# credguard:ignore-file in the first 15 lines skips the whole file.
# pragma: allowlist secret and # noqa: credguard are accepted as aliases.
Configuration
.credguard.toml in the repo root, or a [tool.credguard] table in
pyproject.toml. CLI flags win over the file.
[tool.credguard]
fail_on = "HIGH" # LOW | MEDIUM | HIGH | CRITICAL
exclude_rules = ["credit_card"] # or only_rules = ["private_key", ...]
exclude_globs = ["docs/samples/*", "*.fixture.json"]
exclude_dirs = ["third_party"]
allow_values = [ # regexes matched against the captured value
"^AKIAIOSFODNN7EXAMPLE$",
"^sk_test_",
]
entropy_enabled = true
base64_entropy_threshold = 4.5 # raise to 4.8 for less noise
hex_entropy_threshold = 3.0
max_file_size_kb = 1024
baseline_path = ".credguard-baseline.json"
exclude_dirs and exclude_globs extend the built-in defaults (.git,
node_modules, dist, lockfiles, binaries, minified assets) rather than
replacing them.
Tuning notes
| Symptom | Fix |
|---|---|
Noisy high_entropy_string findings |
Raise base64_entropy_threshold, or set entropy_enabled = false — the provider rules keep working |
| Test fixtures flagged | Add them to exclude_globs, or use sk_test_-style values plus an allow_values entry |
| Docs and samples flagged | Values containing example, changeme, your-…, ${VAR}, os.environ[…] are already ignored |
| Payment-card rule too eager | exclude_rules = ["credit_card"] |
By default fail_on = "HIGH", so MEDIUM entropy findings are reported but do
not block. Against the Python 3.12 standard library (586 files) that yields
19 informational findings and zero blocking ones.
Python API
from credguard import Config, Scanner
scanner = Scanner(Config(entropy_enabled=False))
for finding in scanner.scan_text(open("settings.py").read(), "settings.py"):
print(finding.severity, finding.rule_id, finding.line_no, finding.masked_secret())
What this does not do
- It does not scan history you already pushed. Use
credguard scan --range <first-commit>..HEADto audit, andgit filter-repo/ BFG to rewrite — after rotating the credential. - It is a pattern-and-heuristic scanner, not a proof. Treat a clean run as one layer, alongside secret managers, short-lived credentials and provider-side push protection.
- It never calls a vendor API to check whether a key is live, so nothing leaves your machine.
Development
pip install -e ".[dev]"
pytest -q
credguard scan src # credguard scans itself cleanly
MIT licensed.
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 credguard-0.1.0.tar.gz.
File metadata
- Download URL: credguard-0.1.0.tar.gz
- Upload date:
- Size: 25.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7bee6b9ef788fe357c2f0e0afc3669cd5edab49241d66a33df20daeb2ade45a
|
|
| MD5 |
c2f123f63d385afaf040c7e0d3495344
|
|
| BLAKE2b-256 |
3e4000c364c13b5736466462f2b8d996dba12a37642074965883421b461b08e6
|
File details
Details for the file credguard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: credguard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
246a0cb22ce6f1bb451aa387c4b6c033ce3401f02137ed7dfb3fb2fdb7b99ca1
|
|
| MD5 |
23c10e3d75c592608e7867054d529ddd
|
|
| BLAKE2b-256 |
27d2d7334f7fa25c33d65c4f90c66c5ad23ba6b7a47844f248252bf77f7cb455
|