#!/bin/bash
set -e
echo "π Running pre-commit security checks..."
# Check for potential secrets using gitleaks (industry standard)
echo "π Checking for credentials with gitleaks..."
# Install gitleaks if not available (lightweight, single binary)
if ! command -v gitleaks >/dev/null 2>&1; then
echo "π¦ Installing gitleaks..."
if command -v brew >/dev/null 2>&1; then
brew install gitleaks
elif command -v curl >/dev/null 2>&1; then
# Download gitleaks binary directly
GITLEAKS_VERSION="8.21.2"
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then ARCH="x64"; fi
if [ "$ARCH" = "arm64" ]; then ARCH="arm64"; fi
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_${OS}_${ARCH}.tar.gz" | tar xz
chmod +x gitleaks
sudo mv gitleaks /usr/local/bin/ 2>/dev/null || mv gitleaks ~/.local/bin/ 2>/dev/null || {
echo "β ERROR: Could not install gitleaks. Please install manually:"
echo " brew install gitleaks"
echo " OR download from: https://github.com/gitleaks/gitleaks/releases"
exit 1
}
else
echo "β ERROR: gitleaks not found and cannot auto-install."
echo " Please install gitleaks:"
echo " brew install gitleaks"
echo " OR download from: https://github.com/gitleaks/gitleaks/releases"
exit 1
fi
fi
# Run gitleaks on staged files only
if ! gitleaks protect --staged --no-banner; then
echo ""
echo "β ERROR: Credentials detected by gitleaks!"
echo " Please remove sensitive data before committing."
echo " Use placeholder values like 'pk-lf-your-actual-key' instead."
exit 1
fi
# Check for .env files being committed (should be in .gitignore)
ENV_FILES=$(git diff --cached --name-only | grep -E '^\.env$|^\.env\..*$' || true)
if [ ! -z "$ENV_FILES" ]; then
echo "β ERROR: .env file detected in staged files!"
echo " .env files should never be committed. Add them to .gitignore."
echo " Found: $ENV_FILES"
exit 1
fi
# Check for sensitive file patterns
FORBIDDEN_FILES=$(git diff --cached --name-only | grep -E '\.(langfuse\.json|credentials\.json)$' || true)
if [ ! -z "$FORBIDDEN_FILES" ]; then
echo "β ERROR: Sensitive files detected:"
echo "$FORBIDDEN_FILES"
echo " These files should be in .gitignore, not committed."
exit 1
fi
# Ensure npm is available in PATH
export PATH="/usr/local/bin:/usr/bin:/bin:$PATH"
if ! command -v npm >/dev/null 2>&1; then
echo "β ERROR: npm not found in PATH during git hook execution"
echo " Pre-commit hooks require npm to be available"
exit 1
fi
# Run build to ensure code compiles
echo "π¨ Running build check..."
BUILD_OUTPUT=$(npm run build 2>&1) || BUILD_FAILED=true
if [ "$BUILD_FAILED" = true ]; then
echo "β ERROR: Build failed!"
echo " Please fix TypeScript compilation errors before committing."
echo " Build output: $BUILD_OUTPUT"
exit 1
fi
# Optional: Run tests but don't fail on test failures (due to test data dependency)
echo "π§ͺ Running tests (informational)..."
npm test 2>/dev/null || echo "β οΈ Tests failed - this may be due to missing test data, not code issues"
# If we get here, all security checks passed
echo "β
All pre-commit security checks passed!"