cms.c2sgmbh/scripts/detect-secrets.sh
Martin Porwoll 4d1456fe98 feat: add production deploy health check script
Monitors porwoll.de and blogwoman.de for stale builds caused by
Plesk Git's silent deploy failures (code pulled but build never ran).

- Compares source file timestamps vs .next/BUILD_ID mtime
- HTTP health checks via public URLs
- --alert flag for CMS monitoring API integration
- Runs as cron job every 30 minutes on sv-payload

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 11:42:45 +00:00

162 lines
4.2 KiB
Bash
Executable file

#!/bin/bash
#
# Secret Detection Pre-Commit Hook
#
# Dieses Skript prüft staged Dateien auf potenzielle Secrets.
# Installation: ln -sf ../../scripts/detect-secrets.sh .git/hooks/pre-commit
#
set -e
# Farben für Output
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
echo -e "${GREEN}🔍 Checking for secrets in staged files...${NC}"
# Patterns für potenzielle Secrets
PATTERNS=(
# API Keys und Tokens
'api[_-]?key\s*[:=]\s*["\x27][a-zA-Z0-9_-]{20,}["\x27]'
'token\s*[:=]\s*["\x27][a-zA-Z0-9_-]{20,}["\x27]'
# AWS
'AKIA[0-9A-Z]{16}'
'aws[_-]?secret[_-]?access[_-]?key'
# Private Keys
'-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----'
# Passwörter in Code
'password\s*[:=]\s*["\x27][^"\x27]{8,}["\x27]'
'passwd\s*[:=]\s*["\x27][^"\x27]{8,}["\x27]'
# SMTP Credentials
'smtp[_-]?pass(word)?\s*[:=]\s*["\x27][^"\x27]+["\x27]'
# Database URLs mit Passwörtern
'(postgres|mysql|mongodb)://[^:]+:[^@]+@'
# JWT Tokens (vollständige)
'eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}'
# Generic Secrets
'secret\s*[:=]\s*["\x27][^"\x27]{16,}["\x27]'
# Slack Webhooks
'hooks\.slack\.com/services/T[A-Z0-9]{8}/B[A-Z0-9]{8}/[a-zA-Z0-9]{24}'
# Discord Webhooks
'discord(app)?\.com/api/webhooks/[0-9]+/[a-zA-Z0-9_-]+'
# GitHub Tokens
'ghp_[a-zA-Z0-9]{36}'
'gho_[a-zA-Z0-9]{36}'
'ghu_[a-zA-Z0-9]{36}'
'ghs_[a-zA-Z0-9]{36}'
# SendGrid
'SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}'
# Stripe
'sk_(live|test)_[a-zA-Z0-9]{24,}'
'pk_(live|test)_[a-zA-Z0-9]{24,}'
)
# Dateien die ignoriert werden sollen
IGNORE_FILES=(
'\.min\.js$'
'\.min\.css$'
'package-lock\.json$'
'pnpm-lock\.yaml$'
'yarn\.lock$'
'\.md$'
'\.txt$'
'detect-secrets\.sh$'
'\.example$'
'\.sample$'
'\.spec\.ts$' # Test files may contain example secrets for testing
'\.test\.ts$'
'db-direct\.sh$' # Uses get_password() function for secure password input
'setup-tenants/setup\.sh$' # Uses environment variables, not hardcoded secrets
'check-production-deploys\.sh$' # References env var name CRON_SECRET, not actual secret
)
# Pfade die ignoriert werden sollen
IGNORE_PATHS=(
'node_modules/'
'dist/'
'.next/'
'coverage/'
'.git/'
)
# Prüfe ob wir in einem Git-Repository sind
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo -e "${RED}Error: Not a git repository${NC}"
exit 1
fi
# Hole staged Dateien
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
if [ -z "$STAGED_FILES" ]; then
echo -e "${GREEN}✅ No staged files to check${NC}"
exit 0
fi
FOUND_SECRETS=0
for file in $STAGED_FILES; do
# Überspringe wenn Datei nicht existiert
[ ! -f "$file" ] && continue
# Überspringe ignorierte Pfade
skip=false
for ignore_path in "${IGNORE_PATHS[@]}"; do
if [[ "$file" == *"$ignore_path"* ]]; then
skip=true
break
fi
done
[ "$skip" = true ] && continue
# Überspringe ignorierte Dateitypen
for ignore_file in "${IGNORE_FILES[@]}"; do
if [[ "$file" =~ $ignore_file ]]; then
skip=true
break
fi
done
[ "$skip" = true ] && continue
# Prüfe jedes Pattern
for pattern in "${PATTERNS[@]}"; do
# Hole nur die staged Version der Datei
matches=$(git show ":$file" 2>/dev/null | grep -niE "$pattern" 2>/dev/null || true)
if [ -n "$matches" ]; then
echo -e "${RED}⚠️ Potential secret found in: $file${NC}"
echo -e "${YELLOW}Pattern: $pattern${NC}"
echo "$matches" | head -5
echo ""
FOUND_SECRETS=$((FOUND_SECRETS + 1))
fi
done
done
if [ $FOUND_SECRETS -gt 0 ]; then
echo -e "${RED}❌ Found $FOUND_SECRETS potential secret(s)!${NC}"
echo ""
echo "If these are false positives, you can:"
echo " 1. Add the file to IGNORE_FILES in scripts/detect-secrets.sh"
echo " 2. Use 'git commit --no-verify' to skip this check (not recommended)"
echo " 3. Move secrets to environment variables or .env files"
echo ""
exit 1
fi
echo -e "${GREEN}✅ No secrets found in staged files${NC}"
exit 0