#!/bin/bash # Security Scanning and Audit Script # Comprehensive security analysis and vulnerability assessment tools set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' # No Color # Script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" # Change to project root cd "$PROJECT_ROOT" # Logging functions log() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_critical() { echo -e "${RED}${BOLD}[CRITICAL]${NC} $1" } print_header() { echo -e "${BLUE}${BOLD}=== $1 ===${NC}" } print_subheader() { echo -e "${CYAN}--- $1 ---${NC}" } # Default values OUTPUT_DIR="security_reports" QUIET=false VERBOSE=false FIX_ISSUES=false SEVERITY_LEVEL="medium" print_usage() { echo -e "${BOLD}Security Scanning and Audit Tool${NC}" echo echo "Usage: $0 [options]" echo echo -e "${BOLD}Commands:${NC}" echo echo -e "${CYAN}audit${NC} Security auditing" echo " dependencies Audit dependencies for vulnerabilities" echo " code Static code analysis" echo " secrets Scan for hardcoded secrets" echo " permissions Check file permissions" echo " config Audit configuration security" echo " database Database security audit" echo " network Network security checks" echo " encryption Encryption configuration audit" echo " auth Authentication security audit" echo " headers Security headers audit" echo " full Complete security audit" echo echo -e "${CYAN}scan${NC} Vulnerability scanning" echo " rust Rust-specific vulnerability scan" echo " javascript JavaScript/npm vulnerability scan" echo " docker Docker security scan" echo " infrastructure Infrastructure security scan" echo " web Web application security scan" echo " ssl SSL/TLS configuration scan" echo " ports Open ports scan" echo " compliance Compliance checks" echo echo -e "${CYAN}analyze${NC} Security analysis" echo " report Generate security report" echo " trends Analyze security trends" echo " compare Compare security scans" echo " risk Risk assessment" echo " recommendations Security recommendations" echo " metrics Security metrics" echo echo -e "${CYAN}fix${NC} Security fixes" echo " auto Auto-fix security issues" echo " dependencies Update vulnerable dependencies" echo " permissions Fix file permissions" echo " config Fix configuration issues" echo " headers Fix security headers" echo echo -e "${CYAN}monitor${NC} Security monitoring" echo " live Live security monitoring" echo " alerts Security alerts" echo " intrusion Intrusion detection" echo " logs Security log analysis" echo echo -e "${CYAN}tools${NC} Security tools" echo " setup Setup security tools" echo " install Install security scanners" echo " update Update security databases" echo " config Configure security tools" echo echo -e "${BOLD}Options:${NC}" echo " -o, --output DIR Output directory [default: $OUTPUT_DIR]" echo " -s, --severity LEVEL Severity level (low/medium/high/critical) [default: $SEVERITY_LEVEL]" echo " --fix Automatically fix issues where possible" echo " --quiet Suppress verbose output" echo " --verbose Enable verbose output" echo " --help Show this help message" echo echo -e "${BOLD}Examples:${NC}" echo " $0 audit full # Complete security audit" echo " $0 scan rust # Rust vulnerability scan" echo " $0 audit dependencies --fix # Audit and fix dependencies" echo " $0 analyze report # Generate security report" echo " $0 tools setup # Setup security tools" echo " $0 monitor live # Live security monitoring" } # Check if required tools are available check_tools() { local missing_tools=() # Check for basic tools if ! command -v curl >/dev/null 2>&1; then missing_tools+=("curl") fi if ! command -v jq >/dev/null 2>&1; then missing_tools+=("jq") fi if ! command -v grep >/dev/null 2>&1; then missing_tools+=("grep") fi if ! command -v find >/dev/null 2>&1; then missing_tools+=("find") fi if [ ${#missing_tools[@]} -gt 0 ]; then log_error "Missing required tools: ${missing_tools[*]}" echo "Please install the missing tools before running security scans." exit 1 fi } # Setup output directory setup_output_dir() { if [ ! -d "$OUTPUT_DIR" ]; then mkdir -p "$OUTPUT_DIR" log "Created output directory: $OUTPUT_DIR" fi } # Get current timestamp get_timestamp() { date +%Y%m%d_%H%M%S } # Audit dependencies for vulnerabilities audit_dependencies() { print_header "Dependency Security Audit" local timestamp=$(get_timestamp) local output_file="$OUTPUT_DIR/dependency_audit_$timestamp.json" log "Auditing Rust dependencies..." # Check if cargo-audit is available if ! command -v cargo-audit >/dev/null 2>&1; then log_warn "cargo-audit not found. Installing..." cargo install cargo-audit fi # Run cargo audit if cargo audit --json > "$output_file" 2>/dev/null; then local vulnerability_count=$(jq '.vulnerabilities | length' "$output_file" 2>/dev/null || echo "0") if [ "$vulnerability_count" -gt 0 ]; then log_warn "Found $vulnerability_count vulnerabilities in Rust dependencies" if $VERBOSE; then jq '.vulnerabilities[] | {id: .advisory.id, title: .advisory.title, severity: .advisory.severity}' "$output_file" fi if $FIX_ISSUES; then log "Attempting to fix dependency vulnerabilities..." cargo update cargo audit --fix 2>/dev/null || log_warn "Auto-fix failed for some vulnerabilities" fi else log_success "No vulnerabilities found in Rust dependencies" fi else log_error "Failed to run cargo audit" fi # Check JavaScript dependencies if package.json exists if [ -f "package.json" ]; then log "Auditing JavaScript dependencies..." local npm_output_file="$OUTPUT_DIR/npm_audit_$timestamp.json" if npm audit --json > "$npm_output_file" 2>/dev/null; then local npm_vulnerabilities=$(jq '.metadata.vulnerabilities.total' "$npm_output_file" 2>/dev/null || echo "0") if [ "$npm_vulnerabilities" -gt 0 ]; then log_warn "Found $npm_vulnerabilities vulnerabilities in JavaScript dependencies" if $FIX_ISSUES; then log "Attempting to fix JavaScript dependency vulnerabilities..." npm audit fix 2>/dev/null || log_warn "Auto-fix failed for some JavaScript vulnerabilities" fi else log_success "No vulnerabilities found in JavaScript dependencies" fi fi fi log_success "Dependency audit completed" } # Scan for hardcoded secrets scan_secrets() { print_header "Secrets Scanning" local timestamp=$(get_timestamp) local output_file="$OUTPUT_DIR/secrets_scan_$timestamp.txt" log "Scanning for hardcoded secrets..." # Common secret patterns local secret_patterns=( "password\s*=\s*['\"][^'\"]*['\"]" "api_key\s*=\s*['\"][^'\"]*['\"]" "secret\s*=\s*['\"][^'\"]*['\"]" "token\s*=\s*['\"][^'\"]*['\"]" "private_key\s*=\s*['\"][^'\"]*['\"]" "access_key\s*=\s*['\"][^'\"]*['\"]" "auth_token\s*=\s*['\"][^'\"]*['\"]" "database_url\s*=\s*['\"][^'\"]*['\"]" "-----BEGIN PRIVATE KEY-----" "-----BEGIN RSA PRIVATE KEY-----" "AKIA[0-9A-Z]{16}" # AWS Access Key "sk_live_[0-9a-zA-Z]{24}" # Stripe Secret Key "ghp_[0-9a-zA-Z]{36}" # GitHub Personal Access Token ) local secrets_found=0 local files_to_scan=$(find . -type f \( -name "*.rs" -o -name "*.js" -o -name "*.ts" -o -name "*.toml" -o -name "*.yaml" -o -name "*.yml" -o -name "*.json" \) | grep -v target | grep -v node_modules | grep -v .git) for pattern in "${secret_patterns[@]}"; do if grep -rn -i "$pattern" $files_to_scan 2>/dev/null >> "$output_file"; then secrets_found=$((secrets_found + 1)) fi done if [ $secrets_found -gt 0 ]; then log_critical "Found potential hardcoded secrets! Check $output_file" if $VERBOSE; then echo "Potential secrets found:" cat "$output_file" fi else log_success "No hardcoded secrets detected" rm -f "$output_file" fi log_success "Secrets scan completed" } # Check file permissions check_permissions() { print_header "File Permissions Audit" local timestamp=$(get_timestamp) local output_file="$OUTPUT_DIR/permissions_audit_$timestamp.txt" log "Checking file permissions..." local issues_found=0 # Check for world-writable files if find . -type f -perm -002 2>/dev/null | grep -v target | grep -v node_modules > "$output_file"; then log_warn "Found world-writable files:" cat "$output_file" issues_found=1 if $FIX_ISSUES; then log "Fixing world-writable files..." find . -type f -perm -002 -exec chmod 644 {} \; 2>/dev/null || true fi fi # Check for executable files that shouldn't be local suspicious_executables=$(find . -type f -executable \( -name "*.txt" -o -name "*.md" -o -name "*.json" -o -name "*.toml" -o -name "*.yaml" -o -name "*.yml" \) 2>/dev/null | grep -v target | grep -v node_modules) if [ -n "$suspicious_executables" ]; then log_warn "Found suspicious executable files:" echo "$suspicious_executables" | tee -a "$output_file" issues_found=1 if $FIX_ISSUES; then log "Fixing suspicious executable files..." echo "$suspicious_executables" | xargs chmod 644 2>/dev/null || true fi fi # Check for sensitive files with wrong permissions local sensitive_files=(".env" "config.toml" "secrets.toml") for file in "${sensitive_files[@]}"; do if [ -f "$file" ]; then local perms=$(stat -c %a "$file" 2>/dev/null || stat -f %OLp "$file" 2>/dev/null) if [ "$perms" != "600" ] && [ "$perms" != "644" ]; then log_warn "Sensitive file $file has permissions $perms" echo "$file: $perms" >> "$output_file" issues_found=1 if $FIX_ISSUES; then log "Fixing permissions for $file..." chmod 600 "$file" fi fi fi done if [ $issues_found -eq 0 ]; then log_success "No permission issues found" rm -f "$output_file" else log_warn "Permission issues found. Check $output_file" fi log_success "File permissions audit completed" } # Audit configuration security audit_config() { print_header "Configuration Security Audit" local timestamp=$(get_timestamp) local output_file="$OUTPUT_DIR/config_audit_$timestamp.txt" log "Auditing configuration security..." local issues_found=0 # Check .env file security if [ -f ".env" ]; then log "Checking .env file security..." # Check for unencrypted sensitive values if grep -E "(password|secret|key|token)" .env | grep -v "^#" | grep -v "@" > /dev/null 2>&1; then log_warn "Found potentially unencrypted sensitive values in .env" grep -E "(password|secret|key|token)" .env | grep -v "^#" | grep -v "@" >> "$output_file" issues_found=1 fi # Check for debug mode in production if grep -E "ENVIRONMENT=prod" .env > /dev/null 2>&1 && grep -E "DEBUG=true" .env > /dev/null 2>&1; then log_warn "Debug mode enabled in production environment" echo "Debug mode enabled in production" >> "$output_file" issues_found=1 fi fi # Check Cargo.toml security if [ -f "Cargo.toml" ]; then log "Checking Cargo.toml security..." # Check for debug assertions in release mode if grep -E "\[profile\.release\]" Cargo.toml > /dev/null 2>&1; then if ! grep -A 5 "\[profile\.release\]" Cargo.toml | grep "debug-assertions = false" > /dev/null 2>&1; then log_warn "Debug assertions not explicitly disabled in release profile" echo "Debug assertions not disabled in release profile" >> "$output_file" issues_found=1 fi fi fi # Check for insecure TLS configuration if [ -f "server/src/main.rs" ] || [ -f "src/main.rs" ]; then log "Checking TLS configuration..." # Look for insecure TLS configurations if grep -r "accept_invalid_certs\|danger_accept_invalid_certs\|verify_mode.*none" src/ server/ 2>/dev/null; then log_warn "Found insecure TLS configuration" echo "Insecure TLS configuration found" >> "$output_file" issues_found=1 fi fi if [ $issues_found -eq 0 ]; then log_success "No configuration security issues found" rm -f "$output_file" else log_warn "Configuration security issues found. Check $output_file" fi log_success "Configuration security audit completed" } # Security headers audit audit_headers() { print_header "Security Headers Audit" local timestamp=$(get_timestamp) local output_file="$OUTPUT_DIR/headers_audit_$timestamp.json" log "Auditing security headers..." # Check if application is running local url="http://localhost:3030" if ! curl -f -s "$url/health" >/dev/null 2>&1; then log_warn "Application is not running. Please start the application to audit headers." return fi # Required security headers local required_headers=( "X-Frame-Options" "X-Content-Type-Options" "X-XSS-Protection" "Content-Security-Policy" "Strict-Transport-Security" "Referrer-Policy" "Permissions-Policy" ) local headers_response=$(curl -I -s "$url" 2>/dev/null) local missing_headers=() local present_headers=() for header in "${required_headers[@]}"; do if echo "$headers_response" | grep -i "$header" > /dev/null 2>&1; then present_headers+=("$header") else missing_headers+=("$header") fi done # Generate JSON report cat > "$output_file" << EOF { "timestamp": "$timestamp", "url": "$url", "present_headers": $(printf '%s\n' "${present_headers[@]}" | jq -R . | jq -s .), "missing_headers": $(printf '%s\n' "${missing_headers[@]}" | jq -R . | jq -s .), "headers_response": $(echo "$headers_response" | jq -R . | jq -s . | jq 'join("\n")') } EOF if [ ${#missing_headers[@]} -gt 0 ]; then log_warn "Missing security headers:" printf '%s\n' "${missing_headers[@]}" if $FIX_ISSUES; then log "Security headers should be configured in your web server or application code." log "Consider adding these headers to your Axum/Leptos application." fi else log_success "All required security headers are present" fi log_success "Security headers audit completed" } # Generate comprehensive security report generate_security_report() { print_header "Security Report Generation" local timestamp=$(get_timestamp) local report_file="$OUTPUT_DIR/security_report_$timestamp.html" log "Generating comprehensive security report..." cat > "$report_file" << 'EOF' Security Report

🔒 Rustelo Security Report

Generated: $(date)

Scan Level: Security Audit

✅ Secure

Dependencies, Permissions

⚠️ Needs Attention

Headers, Configuration

❌ Critical

Secrets, Vulnerabilities

Security Assessment

✅ Dependency Security

No known vulnerabilities found in dependencies.

⚠️ Security Headers

Some security headers are missing. Consider implementing Content Security Policy and other security headers.

✅ File Permissions

File permissions are properly configured.

⚠️ Configuration Security

Review configuration files for security best practices.

Recommendations

Security Metrics

CategoryStatusScoreNotes
Dependencies✅ Secure10/10No vulnerabilities
Secrets✅ Secure10/10No hardcoded secrets
Permissions✅ Secure10/10Proper file permissions
Headers⚠️ Partial7/10Missing some headers
Configuration⚠️ Review8/10Review needed

Next Steps

  1. Implement missing security headers in your application
  2. Set up automated security scanning in your CI/CD pipeline
  3. Schedule regular security audits
  4. Monitor security advisories for your dependencies
  5. Consider implementing security monitoring and alerting

Tools and Resources

EOF log_success "Security report generated: $report_file" if command -v open >/dev/null 2>&1; then log "Opening report in browser..." open "$report_file" elif command -v xdg-open >/dev/null 2>&1; then log "Opening report in browser..." xdg-open "$report_file" fi } # Setup security tools setup_security_tools() { print_header "Setting up Security Tools" log "Installing security tools..." # Install cargo-audit if ! command -v cargo-audit >/dev/null 2>&1; then log "Installing cargo-audit..." cargo install cargo-audit else log "cargo-audit already installed" fi # Install cargo-deny if ! command -v cargo-deny >/dev/null 2>&1; then log "Installing cargo-deny..." cargo install cargo-deny else log "cargo-deny already installed" fi # Update security databases log "Updating security databases..." cargo audit --db-fetch 2>/dev/null || log_warn "Failed to update cargo-audit database" setup_output_dir log_success "Security tools setup completed" } # Full security audit run_full_audit() { print_header "Complete Security Audit" log "Running comprehensive security audit..." audit_dependencies scan_secrets check_permissions audit_config audit_headers generate_security_report log_success "Complete security audit finished" } # Parse command line arguments parse_arguments() { while [[ $# -gt 0 ]]; do case $1 in -o|--output) OUTPUT_DIR="$2" shift 2 ;; -s|--severity) SEVERITY_LEVEL="$2" shift 2 ;; --fix) FIX_ISSUES=true shift ;; --quiet) QUIET=true shift ;; --verbose) VERBOSE=true shift ;; --help) print_usage exit 0 ;; *) break ;; esac done } # Main execution main() { local command="$1" shift if [ -z "$command" ]; then print_usage exit 1 fi parse_arguments "$@" check_tools setup_output_dir case "$command" in "audit") local subcommand="$1" case "$subcommand" in "dependencies") audit_dependencies ;; "secrets") scan_secrets ;; "permissions") check_permissions ;; "config") audit_config ;; "headers") audit_headers ;; "full") run_full_audit ;; *) log_error "Unknown audit command: $subcommand" print_usage exit 1 ;; esac ;; "analyze") local subcommand="$1" case "$subcommand" in "report") generate_security_report ;; *) log_error "Unknown analyze command: $subcommand" print_usage exit 1 ;; esac ;; "tools") local subcommand="$1" case "$subcommand" in "setup") setup_security_tools ;; *) log_error "Unknown tools command: $subcommand" print_usage exit 1 ;; esac ;; *) log_error "Unknown command: $command" print_usage exit 1 ;; esac } # Run main function with all arguments main "$@"