Skip to main content

Git pre-commit hook for preventing accidental secret commits

Project description

keygate

PyPI version License: MIT Python 3.11+

A Git pre-commit hook that prevents accidental commits of API keys and passwords.

日本語 | 中文


Why you need this

During development, it's easy to write API keys or passwords directly in code. Once committed with git commit, they become permanently embedded in the repository history.

Even if you delete them later, they remain accessible from past commits — and once exposed on GitHub or similar platforms, they can be exploited almost immediately. There are countless cases of AWS key leaks resulting in massive unexpected bills.

keygate automatically checks before every commit and blocks anything that looks dangerous.


What it detects

  • AWS Access Keys
  • OpenAI API Keys
  • GitHub Tokens
  • Slack Tokens
  • Private Keys (PEM format)
  • JWT Tokens
  • Long random-looking strings (high-entropy detection)
  • Variable names like api_key, password, secret paired with values

Getting started

Step 1: Install

keygate is a Python CLI tool. The easiest way to install it is via pipx.

pipx install keygate

If you don't have pipx, install it with pip install pipx. Using pipx makes the keygate command available from any project directory.

Step 2: Enable the hook

A "hook" is a script Git runs automatically at certain points. Running keygate install-hook makes keygate run automatically on every git commit.

cd path/to/your-project
keygate install-hook

That's all the setup you need.

Step 3: Use it

Just run git add and git commit as usual. If nothing dangerous is found, nothing happens.

If a secret is detected, the commit is blocked like this:

[BLOCK] High confidence secret detected

File: config.py:12
Rule: aws-access-key
Score: 100

Reason:
AWS Access Key detected; sensitive context detected

Remediation:
  - Remove the key from the code
  - Rotate the AWS credentials immediately
  - Use environment variables or AWS IAM roles instead

To ignore:
  Add comment: # keygate: ignore reason="..."

How to read the output:

  • File: config.py:12 — the file and line number where the issue was found
  • Rule: aws-access-key — what was detected
  • Score: 100 — severity (70+ blocks the commit; 40–69 warns only)
  • Reason — why it was flagged
  • Remediation — suggested fixes

Manual scan

You can also scan without using the hook.

git add .
keygate scan

This scans git diff --cached (staged changes only).


Handling false positives

keygate errs on the side of caution, so it may occasionally flag things that aren't real secrets. There are three ways to deal with this.

Option 1: Inline ignore comment

Suppresses detection for that specific line. A reason is required.

api_key = "dummy-key-for-testing"  # keygate: ignore reason="test data"

Option 2: Allowlist paths or patterns

Create a keygate.toml file in your project root and specify paths or patterns to exclude.

[allowlist]
paths = ["vendor/*", "third_party/*"]  # ignore code you don't own
patterns = ["dummy", "example"]         # ignore lines containing these words

Note: Adding tests/* to the allowlist globally will cause keygate to miss real secrets embedded in test code. Use option 1 (inline ignore) or option 3 (baseline) for false positives in tests.

Option 3: Baseline — register existing findings to ignore

Useful when you only want to catch newly added secrets, not existing ones.

keygate baseline create

The current findings are saved to .keygate.baseline.json. From that point on, the same findings are ignored. The file looks like this:

{
  "version": 1,
  "entries": [
    {
      "fingerprint": "e5282a7860678bc768d280eb3e77d2ca8a44286357c743dd024d74fe0605fe09",
      "file_path": "src/app/config.py",
      "line_number": 42,
      "rule_id": "url-credentials",
      "created_at": "2026-04-22T09:30:00+00:00"
    }
  ]
}

The fingerprint is a SHA256 hash of file_path + line_number + matched string. The actual secret value is never stored, so committing the baseline file to Git is safe.

To add newly discovered findings to the baseline:

keygate baseline update

Sharing with your team

We recommend committing .keygate.baseline.json to Git so the whole team uses the same ignore list.

git add .keygate.baseline.json
git commit -m "Add keygate baseline"

New team members only need to run pipx install keygate and keygate install-hook — the shared baseline is picked up automatically.


Configuration (optional)

The defaults work well out of the box, but you can customize behavior by creating keygate.toml in your project root.

[scan]
entropy_threshold = 4.2    # threshold for random-looking strings (lower = stricter)
block_score = 70           # commits are blocked at this score or above

[allowlist]
paths = ["vendor/*"]
patterns = ["dummy", "example"]

[baseline]
path = ".keygate.baseline.json"

If no config file is present, defaults are used.


FAQ

Q. I accidentally committed a secret. What should I do?

A. Revoke (rotate) the key immediately. Removing it from Git history is not enough. Assume any leaked key has already reached an attacker.

Q. How do I temporarily disable the hook?

A. Use git commit --no-verify to skip all hooks including keygate. Not recommended for regular use.

Q. How do we share this across a team?

A. Commit keygate.toml and .keygate.baseline.json to Git. Each team member needs to run keygate install-hook individually.


Disclaimer

keygate is a best-effort detection tool. Please understand the following before use.

  • Detection is not guaranteed: Unknown secret formats, obfuscated values, or custom formats may not be detected (false negatives).
  • False positives can occur: Non-secret strings may be flagged. Use allowlist / baseline / inline ignore to address them.
  • Not a replacement for proper secret management: This tool is an additional safeguard at commit time. Secrets should be managed via environment variables, secret managers, or KMS — never stored in the repository.
  • Hooks can be bypassed: git commit --no-verify skips all hooks. For organizational enforcement, combine with server-side checks (pre-receive hooks, CI scanning, etc.).
  • You are responsible for any leaks caused by missed detections: The authors and contributors accept no liability for damages arising from use of this tool (see LICENSE for details).
  • If a secret is detected, rotate the key promptly: Even if the commit was blocked, the value may remain in local files, editor history, clipboard, or other devices.

This tool is designed as a last-resort safety net to catch human mistakes — not as a substitute for doing secret management correctly.


License

Distributed under the MIT License. Free to use, modify, and redistribute, including for commercial use. See LICENSE for details.

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

keygate-0.1.2.tar.gz (23.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

keygate-0.1.2-py3-none-any.whl (16.8 kB view details)

Uploaded Python 3

File details

Details for the file keygate-0.1.2.tar.gz.

File metadata

  • Download URL: keygate-0.1.2.tar.gz
  • Upload date:
  • Size: 23.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for keygate-0.1.2.tar.gz
Algorithm Hash digest
SHA256 428817e37cd78c86497cee1ad816679940f9cad8f3217a2bfe1f9a9d08a6ca03
MD5 aea86f0d0f36caaf1b22da13a826abeb
BLAKE2b-256 2a3e61fc151fe8a7c392562e22da85ea66f0e6db263cbf04f6edff1148eb3f3b

See more details on using hashes here.

Provenance

The following attestation bundles were made for keygate-0.1.2.tar.gz:

Publisher: publish.yml on kanekoyuichi/keygate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file keygate-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: keygate-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 16.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for keygate-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a3167d6d64fa1022544eb3e049c09de9240baa11ef08090756f1615e7dcd0a45
MD5 3f912c2912fb7ba5d83d37fd86fbeafc
BLAKE2b-256 401aaa9f41056e8bd9a168890a4bf3e6ca43a0b969fff3251df8c4cf36d99dfe

See more details on using hashes here.

Provenance

The following attestation bundles were made for keygate-0.1.2-py3-none-any.whl:

Publisher: publish.yml on kanekoyuichi/keygate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page