145 lines
3.9 KiB
Bash
Executable File
145 lines
3.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Pre-commit hook to check for potential secrets
|
|
# This script checks for common patterns that might indicate secrets being committed
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo "🔍 Checking for potential secrets in staged files..."
|
|
|
|
# Get list of staged files
|
|
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
|
|
|
|
if [ -z "$STAGED_FILES" ]; then
|
|
echo "✅ No files staged for commit"
|
|
exit 0
|
|
fi
|
|
|
|
# Patterns to check for (add more as needed)
|
|
PATTERNS=(
|
|
# RPC URLs and endpoints
|
|
"https://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
|
|
"wss://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
|
|
"ws://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
|
|
"http://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
|
|
|
|
# API keys and tokens (common patterns)
|
|
"[a-zA-Z0-9]{32,}" # Long alphanumeric strings (likely tokens)
|
|
"sk-[a-zA-Z0-9]{20,}" # Stripe-like keys
|
|
"pk_[a-zA-Z0-9]{20,}" # Public keys
|
|
"sk_[a-zA-Z0-9]{20,}" # Secret keys
|
|
|
|
# Private keys and addresses
|
|
"[1-9A-HJ-NP-Za-km-z]{32,}" # Base58 encoded strings (likely private keys)
|
|
"0x[a-fA-F0-9]{40}" # Ethereum addresses
|
|
"[1-9A-HJ-NP-Za-km-z]{44}" # Solana addresses
|
|
|
|
# Common secret patterns
|
|
"password.*=.*['\"][^'\"]{8,}['\"]"
|
|
"secret.*=.*['\"][^'\"]{8,}['\"]"
|
|
"token.*=.*['\"][^'\"]{8,}['\"]"
|
|
"key.*=.*['\"][^'\"]{8,}['\"]"
|
|
"api_key.*=.*['\"][^'\"]{8,}['\"]"
|
|
"private_key.*=.*['\"][^'\"]{8,}['\"]"
|
|
|
|
# Environment variables that might contain secrets
|
|
"ENDPOINT.*=.*['\"][^'\"]{10,}['\"]"
|
|
"WS_ENDPOINT.*=.*['\"][^'\"]{10,}['\"]"
|
|
"GRPC_ENDPOINT.*=.*['\"][^'\"]{10,}['\"]"
|
|
"TOKEN.*=.*['\"][^'\"]{8,}['\"]"
|
|
"API_KEY.*=.*['\"][^'\"]{8,}['\"]"
|
|
"SECRET.*=.*['\"][^'\"]{8,}['\"]"
|
|
)
|
|
|
|
# Files to exclude from checking
|
|
EXCLUDE_PATTERNS=(
|
|
"node_modules"
|
|
".git"
|
|
"*.lock"
|
|
"*.lockb"
|
|
"*.so"
|
|
"*.dll"
|
|
"*.exe"
|
|
"*.bin"
|
|
"*.min.js"
|
|
"*.min.css"
|
|
"*.map"
|
|
"*.log"
|
|
"*.tmp"
|
|
"*.cache"
|
|
"build/"
|
|
"dist/"
|
|
".env.example"
|
|
"scripts/check-secrets.sh" # Exclude this script itself
|
|
)
|
|
|
|
# Function to check if file should be excluded
|
|
should_exclude() {
|
|
local file="$1"
|
|
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
|
|
if [[ "$file" == *"$pattern"* ]] || [[ "$file" =~ $pattern ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Function to check for patterns in a file
|
|
check_file() {
|
|
local file="$1"
|
|
local found_secrets=false
|
|
|
|
# Skip binary files
|
|
if file "$file" | grep -q "binary"; then
|
|
return 0
|
|
fi
|
|
|
|
# Check each pattern
|
|
for pattern in "${PATTERNS[@]}"; do
|
|
if git grep --cached "$pattern" "$file" >/dev/null 2>&1; then
|
|
echo -e "${RED}⚠️ Potential secret found in $file${NC}"
|
|
echo -e "${YELLOW}Pattern: $pattern${NC}"
|
|
git grep --cached "$pattern" "$file" | head -3
|
|
echo ""
|
|
found_secrets=true
|
|
fi
|
|
done
|
|
|
|
if [ "$found_secrets" = true ]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Check each staged file
|
|
has_secrets=false
|
|
for file in $STAGED_FILES; do
|
|
if should_exclude "$file"; then
|
|
echo -e "${GREEN}✅ Skipping excluded file: $file${NC}"
|
|
continue
|
|
fi
|
|
|
|
if ! check_file "$file"; then
|
|
has_secrets=true
|
|
fi
|
|
done
|
|
|
|
if [ "$has_secrets" = true ]; then
|
|
echo -e "${RED}❌ Potential secrets detected!${NC}"
|
|
echo -e "${YELLOW}Please review the above matches and ensure no real secrets are being committed.${NC}"
|
|
echo -e "${YELLOW}If these are false positives, you can:${NC}"
|
|
echo -e "${YELLOW}1. Add the file to .gitignore${NC}"
|
|
echo -e "${YELLOW}2. Use placeholder values instead of real secrets${NC}"
|
|
echo -e "${YELLOW}3. Add the pattern to the exclude list in this script${NC}"
|
|
exit 1
|
|
else
|
|
echo -e "${GREEN}✅ No potential secrets detected${NC}"
|
|
exit 0
|
|
fi |