#!/bin/bash # Check all .env files for required secrets and variables # Identifies missing, empty, or placeholder values set -euo pipefail RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; } log_error() { echo -e "${RED}[✗]${NC} $1"; } log_section() { echo -e "\n${CYAN}=== $1 ===${NC}\n"; } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$PROJECT_ROOT" log_section "Environment Variables and Secrets Audit" # Find all .env files ENV_FILES=$(find . -type f \( -name "*.env*" -o -name ".env" -o -name ".env.*" \) 2>/dev/null | \ grep -vE "(node_modules|venv|\.git|__pycache__|\.pyc)" | \ sort) if [ -z "$ENV_FILES" ]; then log_warn "No .env files found" exit 0 fi log_info "Found $(echo "$ENV_FILES" | wc -l) .env file(s)" echo "" # Common placeholder patterns PLACEHOLDERS=( "your-" "YOUR_" "example.com" "placeholder" "changeme" "TODO" "FIXME" "REPLACE" "PUT_" "SET_" ) # Critical secrets (must be set) CRITICAL_SECRETS=( "CLOUDFLARE_API_TOKEN" "CLOUDFLARE_API_KEY" "PASSWORD" "SECRET" "PRIVATE_KEY" "API_KEY" "TOKEN" ) MISSING=() EMPTY=() PLACEHOLDER_VALUES=() ALL_VARS=() for env_file in $ENV_FILES; do if [ ! -f "$env_file" ]; then continue fi log_section "File: $env_file" # Skip binary files if file "$env_file" | grep -q "binary"; then log_warn "Skipping binary file" continue fi # Check each variable while IFS='=' read -r var_name var_value; do # Skip comments and empty lines [[ "$var_name" =~ ^#.*$ ]] && continue [[ -z "$var_name" ]] && continue # Remove leading/trailing whitespace var_name=$(echo "$var_name" | xargs) var_value=$(echo "$var_value" | xargs) # Remove quotes if present var_value=$(echo "$var_value" | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//") ALL_VARS+=("$var_name") # Check if empty if [ -z "$var_value" ]; then log_error " $var_name: EMPTY" EMPTY+=("$env_file:$var_name") continue fi # Check for placeholders is_placeholder=false for placeholder in "${PLACEHOLDERS[@]}"; do if echo "$var_value" | grep -qi "$placeholder"; then log_warn " $var_name: Contains placeholder pattern" PLACEHOLDER_VALUES+=("$env_file:$var_name:$var_value") is_placeholder=true break fi done if [ "$is_placeholder" = false ]; then # Check if it's a critical secret for secret in "${CRITICAL_SECRETS[@]}"; do if echo "$var_name" | grep -qi "$secret"; then # Check value length (secrets should be substantial) if [ ${#var_value} -lt 10 ]; then log_warn " $var_name: Very short value (may be invalid)" else log_success " $var_name: Set (length: ${#var_value})" fi break fi done fi done < <(grep -v '^#' "$env_file" | grep '=' || true) echo "" done # Summary log_section "Summary" echo "Total .env files checked: $(echo "$ENV_FILES" | wc -l)" echo "Total variables found: ${#ALL_VARS[@]}" echo "Empty variables: ${#EMPTY[@]}" echo "Placeholder values: ${#PLACEHOLDER_VALUES[@]}" echo "" if [ ${#EMPTY[@]} -gt 0 ]; then log_warn "Empty Variables:" for item in "${EMPTY[@]}"; do IFS=':' read -r file var <<< "$item" echo " $file: $var" done echo "" fi if [ ${#PLACEHOLDER_VALUES[@]} -gt 0 ]; then log_warn "Placeholder Values:" for item in "${PLACEHOLDER_VALUES[@]}"; do IFS=':' read -r file var val <<< "$item" echo " $file: $var = $val" done echo "" fi # List all unique variable names log_section "All Unique Variables Found" printf '%s\n' "${ALL_VARS[@]}" | sort -u | while read -r var; do echo " - $var" done echo "" log_section "Recommendations" echo "1. Review empty variables and set appropriate values" echo "2. Replace placeholder values with actual secrets" echo "3. Use secure storage for sensitive values (secrets manager, encrypted files)" echo "4. Document required variables in README or configuration guide" echo "5. Use .env.example files for templates (without real secrets)" echo ""