From 7326f9b0e2ee7ec7f79a097a1f222a52b3e4970c Mon Sep 17 00:00:00 2001 From: DevITWay Date: Sat, 31 Jan 2026 16:39:04 +0000 Subject: [PATCH] chore: add pre-commit hook to prevent sensitive file commits - Whitelist approach: only known safe extensions allowed (.rs, .toml, .yml, etc.) - Block sensitive patterns (.env, .key, .pem, secrets, credentials) - Warn but allow .md files - Check only NEW files, modifications to tracked files always allowed - Block large files (>5MB) with warning - Run cargo fmt check on Rust files - Update CONTRIBUTING.md with hook setup instructions --- .githooks/pre-commit | 142 +++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 3 + 2 files changed, 145 insertions(+) create mode 100755 .githooks/pre-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..d95516a --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,142 @@ +#!/bin/bash +# Pre-commit hook to prevent accidental commits of sensitive files +# Enable: git config core.hooksPath .githooks + +set -e + +RED='\033[0;31m' +YELLOW='\033[1;33m' +GREEN='\033[0;32m' +NC='\033[0m' + +# Allowed file extensions (whitelist) +ALLOWED_EXTENSIONS=( + '\.rs$' + '\.toml$' + '\.lock$' + '\.yml$' + '\.yaml$' + '\.json$' + '\.sh$' + '\.html$' + '\.css$' + '\.js$' + '\.gitignore$' + '\.dockerignore$' + 'Dockerfile$' + 'LICENSE$' + 'Makefile$' +) + +# Extensions that trigger a warning (not blocked) +WARN_EXTENSIONS=( + '\.md$' +) + +# Always blocked patterns (regardless of extension) +BLOCKED_PATTERNS=( + '\.env$' + '\.env\.' + '\.key$' + '\.pem$' + '\.p12$' + '\.pfx$' + '\.htpasswd$' + 'secret' + 'credential' + 'password' + '\.bak$' + '\.swp$' + '\.swo$' + 'node_modules/' + 'target/debug/' + '\.DS_Store' +) + +# Get staged files (only NEW files, not already tracked) +STAGED_FILES=$(git diff --cached --name-only --diff-filter=A) + +if [ -z "$STAGED_FILES" ]; then + # No new files, only modifications to existing - allow + exit 0 +fi + +# Build patterns +ALLOWED_PATTERN=$(IFS='|'; echo "${ALLOWED_EXTENSIONS[*]}") +WARN_PATTERN=$(IFS='|'; echo "${WARN_EXTENSIONS[*]}") +BLOCKED_PATTERN=$(IFS='|'; echo "${BLOCKED_PATTERNS[*]}") + +# Check for blocked patterns first +BLOCKED_FILES=$(echo "$STAGED_FILES" | grep -iE "$BLOCKED_PATTERN" || true) + +if [ -n "$BLOCKED_FILES" ]; then + echo -e "${RED}BLOCKED: Suspicious files detected in commit${NC}" + echo "" + echo -e "${YELLOW}Files:${NC}" + echo "$BLOCKED_FILES" | sed 's/^/ - /' + echo "" + echo "If intentional, use: git commit --no-verify" + exit 1 +fi + +# Check for files with unknown extensions +UNKNOWN_FILES="" +WARN_FILES="" + +while IFS= read -r file; do + [ -z "$file" ] && continue + + if echo "$file" | grep -qE "$BLOCKED_PATTERN"; then + continue # Already handled above + elif echo "$file" | grep -qE "$WARN_PATTERN"; then + WARN_FILES="$WARN_FILES$file"$'\n' + elif ! echo "$file" | grep -qE "$ALLOWED_PATTERN"; then + UNKNOWN_FILES="$UNKNOWN_FILES$file"$'\n' + fi +done <<< "$STAGED_FILES" + +# Warn about .md files +if [ -n "$WARN_FILES" ]; then + echo -e "${YELLOW}WARNING: Markdown files in commit:${NC}" + echo "$WARN_FILES" | sed '/^$/d' | sed 's/^/ - /' + echo "" +fi + +# Block unknown extensions +if [ -n "$UNKNOWN_FILES" ]; then + echo -e "${RED}BLOCKED: Files with unknown extensions:${NC}" + echo "$UNKNOWN_FILES" | sed '/^$/d' | sed 's/^/ - /' + echo "" + echo "Allowed extensions: rs, toml, lock, yml, yaml, json, sh, html, css, js, md" + echo "If intentional, use: git commit --no-verify" + exit 1 +fi + +# Check for large files (>5MB) +LARGE_FILES=$(echo "$STAGED_FILES" | while read f; do + if [ -f "$f" ]; then + size=$(stat -f%z "$f" 2>/dev/null || stat -c%s "$f" 2>/dev/null || echo 0) + if [ "$size" -gt 5242880 ]; then + echo "$f ($(numfmt --to=iec $size 2>/dev/null || echo "${size}B"))" + fi + fi +done) + +if [ -n "$LARGE_FILES" ]; then + echo -e "${YELLOW}WARNING: Large files (>5MB) in commit:${NC}" + echo "$LARGE_FILES" | sed 's/^/ - /' + echo "" +fi + +# Run cargo fmt check if Rust files changed +if git diff --cached --name-only | grep -q '\.rs$'; then + if command -v cargo &> /dev/null; then + if ! cargo fmt --check &> /dev/null; then + echo -e "${RED}BLOCKED: cargo fmt check failed${NC}" + echo "Run: cargo fmt" + exit 1 + fi + fi +fi + +exit 0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a80e46b..5aaabda 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,6 +14,9 @@ Thank you for your interest in contributing to NORA! # Install Rust (if needed) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +# Enable pre-commit hooks (important!) +git config core.hooksPath .githooks + # Build cargo build