cms.c2sgmbh/scripts/detect-secrets.sh
Martin Porwoll fc94531931 feat: implement security hardening module
Security Features:
- Central rate-limiter service with Redis support and memory fallback
  - Predefined limiters: publicApi, auth, email, search, form, strict
  - Automatic cleanup of stale entries
- IP allowlist/blocklist for sensitive endpoints
  - CIDR and wildcard support
  - Configurable via SEND_EMAIL_ALLOWED_IPS, BLOCKED_IPS env vars
- CSRF protection with Double Submit Cookie pattern
  - Token endpoint: GET /api/csrf-token
  - Origin header validation
- Data masking service for sensitive data
  - Automatic redaction of passwords, tokens, API keys
  - Safe logger factory for consistent logging
  - Recursive object masking for audit logs

Secret Scanning:
- Pre-commit hook for local secret detection
- GitHub Actions workflow with Gitleaks and CodeQL
- Gitleaks configuration file
- Dependency vulnerability scanning

Updated:
- /api/send-email now uses central rate-limiter and IP allowlist
- Redis lib exports getRedisClient and isRedisAvailable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 23:04:14 +00:00

157 lines
3.9 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$'
)
# 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