Local pre-push guard for likely secret leaks and private file paths.
Project description
Push Guard
Push Guard is a local Git pre-push guard for likely secret leaks.
It scans the content being pushed, reports likely secret patterns, redacts all matched values, and exits nonzero so Git blocks the push.
Built and maintained by Dragon Lady - github.com/Dragon-Lady - X: @answerislove2
Posture
- Local only.
- No network calls.
- No package installs.
- No target file mutation.
- No secret values printed.
- No tokens, keys, secrets, credentials, file contents, repository contents, or user data are saved by Push Guard.
- Findings store only rule IDs, file paths, line numbers, reasons, and the
literal placeholder
<redacted>. - Uses the
gitsubprocess only to read commit diffs. - No mutation through Git and no other subprocess execution.
- No claim that a repository is clean.
Blocking a push is Git's response to the advisory. Push Guard remains read-only
and does not mutate files. Override is available with git push --no-verify
when the matched value is known not to be a secret.
Push Guard does not send data to any service. It does not phone home, collect telemetry, upload reports, write scan results by default, or retain copies of matched values.
Current Signals
- GitHub classic token prefixes:
ghp_,gho_,ghu_,ghs_,ghr_ - GitHub fine-grained token prefix:
github_pat_ - OpenAI-style
sk-...tokens - AWS access key IDs:
AKIA.../ASIA... - private key block markers
- generic long
api_key,token,secret, orpasswordassignments, including underscore/dash-delimited names such asAWS_SECRET_ACCESS_KEY - Astro config loader/C2 patterns in
astro.config.*and related.gitignorehelper-artifact hiding, based on reported config-as-code supply-chain abuse - OpenClaw dependency versions before
2026.4.23and risky OpenClaw open-DM/wildcard/unsandboxed configuration lines - npm v12 readiness regressions in pushed npm metadata, including old npm pins,
Git or remote tarball dependency sources, and broad repo
.npmrcopt-ins for install-time execution or dependency fetching
All evidence is redacted as <redacted>.
Private Path Rules
Some leaks are not token-shaped. A private handoff lane, a team note, or a credential vault carries no secret pattern in its body, yet pushing it is still a leak. Push Guard also blocks a push when the pushed tree contains a file whose path is private.
It checks the pushed tip tree (not just the diff), so a file that should never have been tracked is flagged on every push until it is removed -- not only on the commit that first added it.
Generic defaults are matched by basename at any depth: *.kdbx, *.pem,
id_rsa, id_ed25519, .env, .env.*, *_keys.json, credentials.json,
.npmrc.
Add your own patterns in a local, git-ignored file at the repo root named
.push-guard-private-paths -- one pattern per line, # for comments. Keeping
your private directory and file names in this local file (and out of version
control) means the names themselves are never committed or pushed:
# directory anywhere in the tree
internal-handoff/
# basename globs
*_NOTES.md
*INTERNAL*
Match rules: a trailing-slash pattern matches that directory anywhere; a glob
(*, ?, [) matches the full path and the basename; a plain token matches an
exact basename or path segment.
Install
pip install push-guard
Install A Repo Hook
Install per repository. Do not install globally.
From the specific repository you want to protect:
cd /path/to/that/repo
push-guard install
Or pass the repository path explicitly:
push-guard install --repo /path/to/that/repo
Push Guard refuses to install into your user home directory by default, even if
your home directory is itself a Git repository. Use --allow-home-repo only when
you intentionally want one broad hook at the home-repo level.
If a pre-push hook already exists, Push Guard refuses to overwrite it. Preserve
and chain existing hooks intentionally, or rerun with --force only when you are
refreshing a Push Guard-managed hook.
Manual hook body, for teams that prefer to wire hooks themselves:
#!/bin/sh
exec python -m push_guard --repo "$(git rev-parse --show-toplevel)"
Run Manually
The CLI expects Git pre-push input on stdin. Manual dry runs are best done from
an actual hook or a test fixture.
python -m push_guard --repo /path/to/repo
Known Limits
- Pattern-based detection can miss secrets or flag non-secrets.
- Long non-secret identifiers in assignments such as
secret = mySuperLongFunctionCallHereWithNoSpacescan match the generic assignment rule. - If a hook is installed from a Git subdirectory, Git may resolve
--repoto a parent repository root. This is acceptable for current diff-only scanning, but future path-relative features such as allowlists or report output must resolve and document the canonical Git root first. - It blocks likely matches; it does not rotate exposed credentials.
- If a real secret was committed, rotate from a clean context after removing it.
- It should be treated as a seatbelt, not a guarantee.
License
Apache-2.0.
Project details
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 push_guard-0.2.2.tar.gz.
File metadata
- Download URL: push_guard-0.2.2.tar.gz
- Upload date:
- Size: 26.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18bde18a6105ce4f4398057be810ca08b903466665d104466fede5e72e61c96a
|
|
| MD5 |
2ddbabfb9e36e3739e8e69d3010b613b
|
|
| BLAKE2b-256 |
aedaa8331a31416d5fed1589dc764a05e72044cc767bfe654a41f30cca886931
|
Provenance
The following attestation bundles were made for push_guard-0.2.2.tar.gz:
Publisher:
publish.yml on Dragon-Lady/push-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
push_guard-0.2.2.tar.gz -
Subject digest:
18bde18a6105ce4f4398057be810ca08b903466665d104466fede5e72e61c96a - Sigstore transparency entry: 1804279799
- Sigstore integration time:
-
Permalink:
Dragon-Lady/push-guard@f286d9b0b1a6f54eea6e04371418aa5cd3106732 -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/Dragon-Lady
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f286d9b0b1a6f54eea6e04371418aa5cd3106732 -
Trigger Event:
release
-
Statement type:
File details
Details for the file push_guard-0.2.2-py3-none-any.whl.
File metadata
- Download URL: push_guard-0.2.2-py3-none-any.whl
- Upload date:
- Size: 19.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c091d83af51e8de3a2d3589783f95e5c2f1ff22c78806d4d01aa7bb089aea3a3
|
|
| MD5 |
a3cff08357ef29439aad836e2337cb38
|
|
| BLAKE2b-256 |
6f0869c518f261487926eaa53a41610dcc1404771465d0c2a34d8bae9b9e31fd
|
Provenance
The following attestation bundles were made for push_guard-0.2.2-py3-none-any.whl:
Publisher:
publish.yml on Dragon-Lady/push-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
push_guard-0.2.2-py3-none-any.whl -
Subject digest:
c091d83af51e8de3a2d3589783f95e5c2f1ff22c78806d4d01aa7bb089aea3a3 - Sigstore transparency entry: 1804279912
- Sigstore integration time:
-
Permalink:
Dragon-Lady/push-guard@f286d9b0b1a6f54eea6e04371418aa5cd3106732 -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/Dragon-Lady
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f286d9b0b1a6f54eea6e04371418aa5cd3106732 -
Trigger Event:
release
-
Statement type: