#!/usr/bin/env bash
# scan-agent-config.sh  -  config-hygiene gate for the shipped agent surface.
#
# Audits the config the pipeline SHIPS (install templates, preferences template,
# agent definitions, MCP helper scripts) for security problems before release:
#   HIGH   - hardcoded secrets; hook commands that eval/execute inspected input;
#            permission bypass flags baked into a shipped template.
#   MEDIUM - unpinned/remote-install supply-chain patterns (curl|bash, npx -y);
#            blanket Bash(*) permission allow.
#
# Read-only. Never prints a secret value (reports file + rule only). Self-contained
# (no external scanner dependency). Exit 1 if any HIGH finding, else 0.
#
# Inspired by config-audit tools like ecc-agentshield, but rewritten as a
# first-party, dependency-free gate over this repo's own shipped surface.

set -uo pipefail

# ROOT defaults to the repo root; SCAN_ROOT overrides it (used by the smoke test
# to point at a fixture tree of planted-bad configs).
ROOT="${SCAN_ROOT:-$(cd "$(dirname "$0")/../.." && pwd)}"

HIGH=0; MED=0
high() { HIGH=$((HIGH+1)); echo "  [HIGH]   $1"; }
med()  { MED=$((MED+1));  echo "  [MEDIUM] $1"; }

# Shipped config surface (globs expanded safely; missing paths are skipped).
TARGETS=()
add() { [ -e "$1" ] && TARGETS+=("$1"); }
add "$ROOT/install/templates/claude-hooks.json"
add "$ROOT/install/templates/copilot-instructions.md"
add "$ROOT/pipeline/preferences-template.json"
for f in "$ROOT"/pipeline/agents/*.md; do add "$f"; done
# (figma component skills + their scripts now live in the ai-*-toolkit
#  marketplace plugin, not in this repo, so there is nothing figma to scan here.)
add "$ROOT/pipeline/scripts/agent-guard.sh"
add "$ROOT/pipeline/scripts/pre-commit-check.sh"

rel() { echo "${1#$ROOT/}"; }

echo "→ scanning ${#TARGETS[@]} shipped config files"

for f in "${TARGETS[@]}"; do
  [ -f "$f" ] || continue
  r="$(rel "$f")"

  # --- HIGH: hardcoded secrets (high-signal prefixes only; report file, not value)
  if grep -EqI '(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{60,}|xox[baprs]-[A-Za-z0-9-]{12,}|sk_live_[A-Za-z0-9]{20,}|AIza[0-9A-Za-z_-]{35}|npm_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY-----' "$f" 2>/dev/null; then
    high "hardcoded secret / token in $r"
  fi
  if grep -Eq '"type"[[:space:]]*:[[:space:]]*"service_account"' "$f" 2>/dev/null; then
    high "embedded service-account JSON in $r"
  fi

  # --- HIGH: permission bypass baked into a shipped template
  if grep -Eq 'skipDangerousModePermissionPrompt"?[[:space:]]*:[[:space:]]*true|--dangerously-skip-permissions|"permissions"[[:space:]]*:[[:space:]]*"?(allow-all|bypass)' "$f" 2>/dev/null; then
    high "permission bypass flag in shipped template: $r"
  fi

  # --- MEDIUM: blanket Bash allow
  if grep -Eq '"Bash\(\*\)"|"Bash\(:\*\)"|Bash\(\*:\*\)' "$f" 2>/dev/null; then
    med "blanket Bash(*) permission in $r"
  fi

  # --- MEDIUM: remote-install supply-chain patterns
  if grep -Eq 'curl[^|]*\|[[:space:]]*(sudo[[:space:]]+)?(ba)?sh|wget[^|]*\|[[:space:]]*(ba)?sh' "$f" 2>/dev/null; then
    med "pipe-to-shell remote install (curl|bash) in $r"
  fi
  if grep -Eq '(^|[^A-Za-z])npx[[:space:]]+-y[[:space:]]|npx[[:space:]]+--yes[[:space:]]' "$f" 2>/dev/null; then
    med "unpinned 'npx -y' auto-install in $r"
  fi
done

# --- HIGH: hook commands must only invoke vetted scripts, never inline eval -----
HOOKS="$ROOT/install/templates/claude-hooks.json"
if [ -f "$HOOKS" ] && command -v python3 >/dev/null 2>&1; then
  bad="$(python3 - "$HOOKS" <<'PY' 2>/dev/null || true
import json, re, sys
try:
    t = json.load(open(sys.argv[1]))
except Exception:
    sys.exit(0)
bad = []
for _event, entries in (t.get("hooks") or {}).items():
    for e in entries:
        for h in e.get("hooks", []):
            c = h.get("command", "")
            # allow only: `bash $HOME/.claude/scripts/<name>` (our vetted scripts)
            if not re.fullmatch(r'bash \$HOME/\.claude/scripts/[A-Za-z0-9._-]+', c.strip()):
                bad.append(c)
            if re.search(r'\beval\b|\$\(|`', c):
                bad.append(c)
print("\n".join(bad))
PY
)"
  if [ -n "$bad" ]; then
    high "hooks template has a non-vetted or eval-bearing hook command"
  fi
fi

echo ""
echo "══ config-hygiene: $HIGH high, $MED medium ══"
if [ "$HIGH" -gt 0 ]; then
  echo "FAIL: high-severity config findings must be fixed before release."
  exit 1
fi
exit 0
