Git Hooks Patterns
This skill provides guidance on git hooks implementation and sensitive data detection in the dotfiles project.
Overview
The project uses git hooks to enforce security and quality standards before commits. Hooks are automatically installed as symlinks during dotfiles setup, making them easy to maintain and version control.
Key Features
- •Pre-commit scanning: Detect sensitive information before it reaches the repository
- •Automatic installation: Hooks are installed as symlinks during
dotfiles.sh -Iordotfiles.ps1 -Install - •Pattern-based detection: Configurable patterns in
hooks/sensitive-patterns.ini - •Cross-platform: Works on Linux, macOS, and Windows (via Git Bash)
- •Bypassable: Use
--no-verifyfor false positives
Hooks are stored in the hooks/ directory and automatically installed as symlinks in .git/hooks/. See the contributing-guide skill for the complete development workflow.
Available Hooks
pre-commit Hook
Purpose: Scan staged changes for sensitive information before allowing commits.
Location: hooks/pre-commit
Implementation: POSIX shell script (#!/bin/sh)
Detection Patterns: Defined in hooks/sensitive-patterns.ini
Hook Installation
Automatic Installation
Hooks are automatically installed during dotfiles setup:
Linux:
./dotfiles.sh -I
Windows:
.\dotfiles.ps1 -Install
Implementation
The installation creates symlinks from .git/hooks/ to hooks/:
ln -sf "../../hooks/pre-commit" ".git/hooks/pre-commit"
Benefits:
- •Updates to hooks in the repository are immediately active
- •No reinstallation needed when hooks change
- •Version controlled hook logic
Sensitive Data Detection
Pattern Configuration Format
Patterns are defined in hooks/sensitive-patterns.ini using INI sections:
# Section headers organize patterns by type [section-name] pattern-one pattern-two [another-section] more-patterns
Pattern Categories
- •
api-keys: Generic API keys and secret keys - •
passwords: Password assignments and configurations - •
tokens: Bearer tokens, access tokens, authorization headers - •
aws: AWS credentials (access keys, secret keys) - •
private-keys: PEM-formatted private keys (RSA, DSA, EC, OpenSSH) - •
github: GitHub personal access tokens - •
gitlab: GitLab personal access tokens - •
oauth: OAuth client secrets - •
database: Database connection strings with credentials - •
slack: Slack tokens and webhooks - •
stripe: Stripe API keys - •
google: Google Cloud and Firebase API keys - •
heroku: Heroku API keys - •
generic: High-entropy generic secrets
Pattern Format
Patterns use Extended Regular Expressions (ERE):
- •Case-insensitive matching
- •No need for escape characters for most metacharacters
- •Supports alternation:
(pattern1|pattern2) - •Supports character classes:
[a-zA-Z0-9]
Example Patterns
[api-keys]
# Matches: apikey=xxx, api_key = xxx, API_KEY: xxx
(apikey|api_key)[\s]*[=:]
# Matches: secret_key = xxx
secret_key[\s]*[=:]
[passwords]
# Matches: password=xxx, passwd: xxx
(password|passwd|pwd)[\s]*[=:]
[tokens]
# Matches: Authorization: Bearer xxx
authorization[\s]*:[\s]*bearer[\s]+[a-z0-9._-]{20,}
[private-keys]
# Matches: -----BEGIN RSA PRIVATE KEY-----
-----BEGIN[\s]+(RSA|DSA|EC|OPENSSH)[\s]+PRIVATE[\s]+KEY-----
Hook Behavior
When Sensitive Data Detected
The hook prints an error message and aborts the commit:
ERROR: Potential sensitive information detected! ====================================================== In file: config/example.py Pattern matched: (apikey|api_key)[\s]*[=:] Commit aborted to prevent leaking sensitive data. Please review and remove any sensitive information. If this is a false positive, use: git commit --no-verify
Bypassing the Hook
Use --no-verify flag to bypass (use with caution):
git commit --no-verify
When to bypass:
- •False positives (e.g., example code, documentation)
- •Testing or dummy credentials
- •Pattern matches non-sensitive content
Never bypass for:
- •Real API keys or tokens
- •Actual passwords
- •Production credentials
- •Private keys
Adding New Patterns
1. Identify the Pattern Type
Determine which section the pattern belongs to or create a new section.
2. Write the Pattern
Use Extended Regular Expression syntax:
[new-section] # Match specific format pattern[\s]*[=:][\s]*value # Match alternatives (option1|option2|option3) # Match character ranges [a-zA-Z0-9_-]+
3. Test the Pattern
Test with grep using ERE mode:
echo "apikey=secret123" | grep -E "(apikey|api_key)[\s]*[=:]"
4. Add to sensitive-patterns.ini
[section-name] your-new-pattern
5. Test the Hook
Stage a test file and attempt to commit:
echo "apikey=test" > test.txt git add test.txt git commit -m "Test" # Should be blocked rm test.txt
Pattern Guidelines
Reduce False Positives
- •Be specific: Match context around the pattern
- •Use word boundaries when appropriate
- •Consider common usage patterns
- •Test against real files
Increase Detection
- •Consider variations:
api_key,apiKey,APIKEY - •Match common delimiters:
=,:," : " - •Allow whitespace:
[\s]* - •Match value patterns when possible
Example: Good vs. Bad
Bad (too many false positives):
[passwords] password
Good (specific context):
[passwords] (password|passwd|pwd)[\s]*[=:]
Cross-Platform Compatibility
Shell Compatibility
Hooks use POSIX shell (#!/bin/sh):
- •Compatible with Linux, macOS, Windows (Git Bash)
- •No Bash-specific features
- •Standard utilities only (grep, git)
Testing on Windows
Git for Windows includes Git Bash:
# Hook runs in Git Bash automatically git commit -m "Test"
Hook Development Patterns
Script Structure
#!/bin/sh
set -o errexit # Exit on error
set -o nounset # Exit on undefined variable
# Configuration
PATTERNS_FILE="hooks/sensitive-patterns.ini"
REPO_ROOT="$(git rev-parse --show-toplevel)"
# Main logic
main() {
# Get staged files
files=$(git diff --cached --name-only --diff-filter=ACM)
# Process files
for file in $files; do
# Check patterns
done
}
main
Reading INI Patterns
# Read all patterns from INI file (skip comments and blank lines)
patterns=$(grep -v '^#' "$PATTERNS_FILE" | grep -v '^\[' | grep -v '^$')
# Check each pattern
for pattern in $patterns; do
if git diff --cached -- "$file" | grep -iE "$pattern" >/dev/null; then
# Pattern matched
fi
done
Error Reporting
# Clear error message cat <<EOF ERROR: Potential sensitive information detected! ====================================================== In file: $file Pattern matched: $pattern Commit aborted to prevent leaking sensitive data. EOF exit 1 # Non-zero exit aborts commit
Rules
- •All hooks must use POSIX shell (
#!/bin/sh) - •Hooks are installed as symlinks (changes apply immediately)
- •Never commit real credentials (even in comments)
- •Test hooks before committing changes
- •Document patterns in sensitive-patterns.ini
- •Provide clear error messages
- •Allow bypass with
--no-verifyfor false positives - •Maintain cross-platform compatibility