diff --git a/templates/pre-commit.sh b/templates/pre-commit.sh new file mode 100644 index 0000000..1985fc6 --- /dev/null +++ b/templates/pre-commit.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# ============================================================================= +# .git/hooks/pre-commit +# Fail-safe security hook: Prevents plaintext leaks of sensitive data. +# ============================================================================= + +set -euo pipefail + +# Directories that MUST be encrypted +PRIVATE_PATTERNS=("raw/private/" "wiki/private/") +FAILED=0 + +# Get staged files (excluding deletions) +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || true) + +if [[ -z "$STAGED_FILES" ]]; then + exit 0 +fi + +for pattern in "${PRIVATE_PATTERNS[@]}"; do + while IFS= read -r file; do + if [[ "$file" == ${pattern}* ]]; then + # Check encryption status via git-crypt + STATUS=$(git-crypt status "$file" 2>/dev/null || echo "error") + if echo "$STATUS" | grep -q "not encrypted"; then + echo -e "\n\033[0;31m[SECURITY ALERT] PLAINTEXT LEAK DETECTED\033[0m" + echo "-----------------------------------------------------------" + echo "File: $file" + echo "Status: This file is in a private/ folder but is NOT encrypted." + echo "Action: Fix your .gitattributes or run 'git-crypt init'." + echo "-----------------------------------------------------------" + FAILED=1 + fi + fi + done <<< "$STAGED_FILES" +done + +if [[ "$FAILED" -ne 0 ]]; then + echo -e "\033[0;31mCommit blocked for security reasons.\033[0m\n" + exit 1 +fi + +exit 0