Production-grade pre-commit hook utility for zero-latency git diff token scanning

#!/usr/bin/env python3
"""
Fast Diff Token Scanner.
Reads unified git diff from STDIN, checks only added lines (+),
and flags API keys, private keys, high-entropy tokens.
"""
import sys
import re
import math
from typing import List, Tuple
# Pre-compiled high-confidence secret regex patterns
SECRET_PATTERNS = [
("AWS Access Key ID", re.compile(r"\b(AKIA[0-9A-Z]{16})\b")),
("GitHub Personal Access Token", re.compile(r"\b(gh[pousr]_[A-Za-z0-9_]{36,255})\b")),
("Generic Bearer Token", re.compile(r"(?i)bearer\s+([a-zA-Z0-9_\-\.]{24,})")),
("RSA/ECDSA Private Key Header", re.compile(r"-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----")),
("Slack API Token", re.compile(r"\b(xox[p|b|o|a]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*)\b")),
("Stripe Secret Key", re.compile(r"\b(sk_live_[0-9a-zA-Z]{24})\b")),
]
def shannon_entropy(text: str) -> float:
"""Calculate Shannon entropy bits per character."""
if not text:
return 0.0
length = len(text)
counts = [0] * 256
for b in text.encode("utf-8", errors="ignore"):
counts[b] += 1
entropy = 0.0
for count in counts:
if count > 0:
p = count / length
entropy -= p * math.log2(p)
return entropy
def scan_diff(stream) -> List[Tuple[str, str, str]]:
findings = []
current_file = "unknown"
for line in stream:
line_clean = line.rstrip("\r\n")
# Track file name
if line_clean.startswith("+++ b/"):
current_file = line_clean[6:]
continue
elif line_clean.startswith("--- ") or line_clean.startswith("diff --git"):
continue
# Only inspect additions
if not line_clean.startswith("+") or line_clean.startswith("+++"):
continue
content = line_clean[1:] # strip leading '+'
# 1. Regex pattern checks
for pat_name, regex in SECRET_PATTERNS:
match = regex.search(content)
if match:
snippet = match.group(0)[:12] + "..."
findings.append((current_file, pat_name, snippet))
# 2. Shannon entropy check for alphanumeric tokens > 24 chars
words = re.findall(r"[A-Za-z0-9+/=_\-]{24,}", content)
for w in words:
ent = shannon_entropy(w)
if ent >= 4.4:
snippet = w[:10] + "..." + w[-4:]
findings.append((current_file, f"High Entropy Token ({ent:.2f} bits)", snippet))
return findings
def main():
findings = scan_diff(sys.stdin)
if not findings:
sys.exit(0)
print("\n🚨 Potential credentials found in git diff:")
for file_path, rule, snippet in findings:
print(f" - [{rule}] in {file_path}: {snippet}")
print()
sys.exit(1)
if __name__ == "__main__":
main()

Zero-Latency Git Diff Secret Guard Installation

Protect your repositories from accidental secret commits by running this pre-commit scanner locally.

Method 1: Local .git/hooks Installation

  1. Copy the scripts into your repository's hook directory:
    cp pre-commit-secret-guard.sh .git/hooks/pre-commit
    cp fast_diff_check.py .git/hooks/fast_diff_check.py
    chmod +x .git/hooks/pre-commit .git/hooks/fast_diff_check.py
  2. Test the hook by staging a dummy high-entropy secret:
    echo "API_KEY=AKIAIOSFODNN7EXAMPLE" >> test.env
    git add test.env
    git commit -m "Test commit"
    # Hook will abort commit and alert you!

Method 2: Global Git Template

To enforce this check across all newly cloned repositories:

git config --global init.templateDir ~/.git-templates
mkdir -p ~/.git-templates/hooks
cp pre-commit-secret-guard.sh ~/.git-templates/hooks/pre-commit
cp fast_diff_check.py ~/.git-templates/hooks/fast_diff_check.py
chmod +x ~/.git-templates/hooks/pre-commit ~/.git-templates/hooks/fast_diff_check.py
#!/usr/bin/env bash
#
# Git pre-commit hook to prevent accidental secret leakage.
# Scans only staged changes for zero-latency commits.
set -e
# Redirect output to stderr
exec 1>&2
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCANNER="$SCRIPT_DIR/fast_diff_check.py"
# If python scanner is not found in hooks dir, search PATH
if [ ! -f "$SCANNER" ]; then
SCANNER="fast_diff_check.py"
fi
echo "🔍 [Secret Guard] Scanning staged changes for credentials..."
# Run secret scanner on staged git diff
if git rev-parse --verify HEAD >/dev/null 2>&1; then
AGAINST=HEAD
else
# Initial commit: diff against empty tree object
AGAINST="$(git hash-object -t tree /dev/null)"
fi
git diff --cached --unified=0 "$AGAINST" | python3 "$SCANNER"
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "❌ [Secret Guard] Commit aborted due to detected high-entropy token or secret pattern!"
echo "💡 If this is an intentional commit or false positive, use git commit --no-verify"
exit 1
fi
echo "✅ [Secret Guard] Staged changes verified clean."
exit 0
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论