#!/bin/bash # Sovereign security scanning — local developer workflow # Usage: security-scan.sh [path] [--fix] # Runs: govulncheck, gitleaks, trivy # No cloud dependencies. PCI DSS Req 6.3.2 / 11.3 compliant. set -euo pipefail TARGET="${1:-.}" FIX_MODE="${2:-}" PASS=0 FAIL=0 WARN=0 GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[0;33m' DIM='\033[0;90m' RESET='\033[0m' header() { echo -e "\n${GREEN}=== $1 ===${RESET}"; } pass() { echo -e " ${GREEN}PASS${RESET} $1"; ((PASS++)); } fail() { echo -e " ${RED}FAIL${RESET} $1"; ((FAIL++)); } warn() { echo -e " ${YELLOW}WARN${RESET} $1"; ((WARN++)); } dim() { echo -e " ${DIM}$1${RESET}"; } echo "Security Scan: $(realpath "$TARGET")" echo "Date: $(date -u +"%Y-%m-%dT%H:%M:%SZ")" # --- Go vulnerability check --- if [ -f "$TARGET/go.mod" ]; then header "Go Vulnerability Check (govulncheck)" GOVULNCHECK=$(command -v govulncheck 2>/dev/null || echo "$HOME/go/bin/govulncheck") if [ -x "$GOVULNCHECK" ]; then GOVULN_OUT=$( (cd "$TARGET" && $GOVULNCHECK ./... 2>&1) || true) if echo "$GOVULN_OUT" | grep -q "No vulnerabilities found"; then pass "No Go vulnerabilities found" else VULN_COUNT=$(echo "$GOVULN_OUT" | grep -c "^Vulnerability #" || true) if [ "$VULN_COUNT" -gt 0 ]; then warn "$VULN_COUNT Go vulnerabilities found (run govulncheck ./... for details)" else pass "govulncheck completed" fi fi else dim "govulncheck not installed (go install golang.org/x/vuln/cmd/govulncheck@latest)" fi fi # --- Secret detection --- header "Secret Detection (gitleaks)" GITLEAKS=$(command -v gitleaks 2>/dev/null || echo "$HOME/.local/bin/gitleaks") if [ -x "$GITLEAKS" ]; then if $GITLEAKS detect --source "$TARGET" --no-banner --no-git 2>&1 | grep -q "no leaks found"; then pass "No secrets detected in working tree" else LEAK_COUNT=$($GITLEAKS detect --source "$TARGET" --no-banner --no-git --report-format json --report-path /dev/stdout 2>/dev/null | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null || echo "?") fail "$LEAK_COUNT potential secrets found (run gitleaks detect --source $TARGET -v)" fi else dim "gitleaks not installed" fi # --- Dependency & filesystem scan --- header "Dependency Scan (trivy)" TRIVY=$(command -v trivy 2>/dev/null || echo "$HOME/.local/bin/trivy") if [ -x "$TRIVY" ]; then TRIVY_OUT=$($TRIVY fs --scanners vuln --severity HIGH,CRITICAL --quiet "$TARGET" 2>&1 || true) if echo "$TRIVY_OUT" | grep -q "Total: 0"; then pass "No HIGH/CRITICAL vulnerabilities in dependencies" elif [ -z "$TRIVY_OUT" ]; then pass "No vulnerable dependencies found" else TRIVY_VULNS=$(echo "$TRIVY_OUT" | grep -oP 'Total: \K\d+' | awk '{s+=$1}END{print s}' 2>/dev/null || echo "?") warn "$TRIVY_VULNS HIGH/CRITICAL dependency vulnerabilities" echo "$TRIVY_OUT" | grep -E '│|Total:' | head -20 fi else dim "trivy not installed" fi # --- Summary --- echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo -e " ${GREEN}PASS: $PASS${RESET} ${YELLOW}WARN: $WARN${RESET} ${RED}FAIL: $FAIL${RESET}" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" if [ "$FAIL" -gt 0 ]; then exit 1 fi exit 0