From b4116e8baebb5c84805649adb1ed4d623cd532ab Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Mon, 16 Mar 2026 11:30:11 -0700 Subject: [PATCH] feat: add pre-commit sensitive file blocker and support request issue template Completes issue #7 (public mirror setup): - .githooks/pre-commit: blocks sensitive filenames (.env, *.key, *.pem, id_rsa, credentials.json, etc.) and credential content patterns (private key headers, AWS keys, GitHub tokens, Stripe secret keys, generic API key assignments) from being committed - .github/ISSUE_TEMPLATE/support_request.md: third issue template for usage questions alongside existing bug report and feature request --- .githooks/pre-commit | 84 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/support_request.md | 26 +++++++ 2 files changed, 110 insertions(+) create mode 100755 .githooks/pre-commit create mode 100644 .github/ISSUE_TEMPLATE/support_request.md diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..bb9bb7f --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# .githooks/pre-commit — blocks sensitive files and credential patterns from being committed +set -euo pipefail + +RED='\033[0;31m'; YELLOW='\033[1;33m'; BOLD='\033[1m'; NC='\033[0m' + +BLOCKED=0 +STAGED=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null) + +if [[ -z "$STAGED" ]]; then + exit 0 +fi + +# ── Blocked filenames ────────────────────────────────────────────────────────── +BLOCKED_FILES=( + ".env" + ".env.local" + ".env.production" + ".env.staging" + "*.pem" + "*.key" + "*.p12" + "*.pfx" + "id_rsa" + "id_ecdsa" + "id_ed25519" + "id_dsa" + "*.ppk" + "secrets.yml" + "secrets.yaml" + "credentials.json" + "service-account*.json" + "*.keystore" + "htpasswd" + ".htpasswd" +) + +while IFS= read -r file; do + filename="$(basename "$file")" + for pattern in "${BLOCKED_FILES[@]}"; do + # shellcheck disable=SC2254 + case "$filename" in + $pattern) + echo -e "${RED}BLOCKED:${NC} ${BOLD}$file${NC} matches blocked filename pattern '${YELLOW}$pattern${NC}'" + BLOCKED=1 + ;; + esac + done +done <<< "$STAGED" + +# ── Blocked content patterns ─────────────────────────────────────────────────── +declare -A CONTENT_PATTERNS=( + ["RSA/EC private key header"]="-----BEGIN (RSA|EC|DSA|OPENSSH) PRIVATE KEY" + ["AWS access key"]="AKIA[0-9A-Z]{16}" + ["GitHub token"]="ghp_[A-Za-z0-9]{36}" + ["Generic API key assignment"]="(api_key|API_KEY|secret_key|SECRET_KEY)\s*=\s*['\"][A-Za-z0-9_\-]{16,}" + ["Stripe secret key"]="sk_(live|test)_[A-Za-z0-9]{24,}" + ["Forgejo/Gitea token (40 hex chars)"]="[a-f0-9]{40}" +) + +while IFS= read -r file; do + # Skip binary files + if git diff --cached -- "$file" | grep -qP "^\+.*\x00"; then + continue + fi + for label in "${!CONTENT_PATTERNS[@]}"; do + pattern="${CONTENT_PATTERNS[$label]}" + matches=$(git diff --cached -- "$file" | grep "^+" | grep -cP "$pattern" 2>/dev/null || true) + if [[ "$matches" -gt 0 ]]; then + echo -e "${RED}BLOCKED:${NC} ${BOLD}$file${NC} contains pattern matching '${YELLOW}$label${NC}'" + BLOCKED=1 + fi + done +done <<< "$STAGED" + +# ── Result ───────────────────────────────────────────────────────────────────── +if [[ "$BLOCKED" -eq 1 ]]; then + echo "" + echo -e "${RED}Commit rejected.${NC} Remove sensitive files/content before committing." + echo -e "To bypass in an emergency: ${YELLOW}git commit --no-verify${NC} (use with extreme caution)" + exit 1 +fi + +exit 0 diff --git a/.github/ISSUE_TEMPLATE/support_request.md b/.github/ISSUE_TEMPLATE/support_request.md new file mode 100644 index 0000000..66a5c07 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/support_request.md @@ -0,0 +1,26 @@ +--- +name: Support Request +about: Ask a question or get help using Peregrine +title: '[Support] ' +labels: question +assignees: '' +--- + +## What are you trying to do? + + + +## What have you tried? + + + +## Environment + +- OS: +- Install method: +- Peregrine version: +- LLM backend: + +## Logs or screenshots + +