Skip to content
Visibility internal Owner _ Approver _ Created _ Updated _

scan-static.sh



FieldValue
TypeShell
SourceForge/Skills/Security_Scan/scripts/scan-static.sh
ParentForge
GitHubForge/Skills/Security_Scan/scripts/scan-static.sh

This page is auto-generated. Edit the source to change the content.



#!/usr/bin/env bash
# Runs the static scanners against a repo. Skips whatever isn't installed.
# Exits 0 even when findings exist -- findings are for triage, not a gate.
# Use --fail-on-critical in CI if you want it to block.
#
# Usage: scan-static.sh [--repo PATH] [--out DIR] [--fail-on-critical]
set -uo pipefail

REPO="."
OUT=".security-scan/results"
FAIL_ON_CRITICAL=0

while [[ $# -gt 0 ]]; do
  case "$1" in
    --repo) REPO="$2"; shift 2 ;;
    --out) OUT="$2"; shift 2 ;;
    --fail-on-critical) FAIL_ON_CRITICAL=1; shift ;;
    *) echo "unknown argument: $1" >&2; exit 2 ;;
  esac
done

[[ -d "$REPO" ]] || { echo "no such directory: $REPO" >&2; exit 2; }
mkdir -p "$OUT"
STAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "{\"started\":\"$STAMP\",\"repo\":\"$REPO\"}" > "$OUT/run.json"

run() {
  local label="$1"; shift
  echo ">>> $label"
  if "$@"; then echo "    done"; else echo "    exited $? (findings or error -- see output file)"; fi
}

if command -v semgrep >/dev/null 2>&1; then
  # p/security-audit is noisier but catches more; p/owasp-top-ten maps to categories.
  run "Semgrep" semgrep scan \
    --config=p/security-audit --config=p/owasp-top-ten --config=p/secrets \
    --sarif --output="$OUT/semgrep.sarif" --metrics=off --quiet "$REPO"
fi

if command -v trivy >/dev/null 2>&1; then
  run "Trivy (filesystem: deps, secrets, misconfig)" trivy fs \
    --scanners vuln,secret,misconfig \
    --format sarif --output "$OUT/trivy.sarif" --quiet "$REPO"
  run "Trivy (SBOM)" trivy fs \
    --format cyclonedx --output "$OUT/sbom.cdx.json" --quiet "$REPO"
fi

if command -v gitleaks >/dev/null 2>&1; then
  # Scans full git history, not just the working tree -- that's the point of it.
  # `git` subcommand replaced the deprecated `detect` in v8.19.0.
  if [[ -d "$REPO/.git" ]]; then
    run "Gitleaks (git history)" gitleaks git "$REPO" \
      --report-format sarif --report-path "$OUT/gitleaks.sarif" --redact --no-banner
  else
    echo ">>> Gitleaks: $REPO is not a git repo, scanning files only (history not checked)"
    run "Gitleaks (directory)" gitleaks dir "$REPO" \
      --report-format sarif --report-path "$OUT/gitleaks.sarif" --redact --no-banner
  fi
fi

if command -v checkov >/dev/null 2>&1; then
  run "Checkov (IaC)" checkov --directory "$REPO" \
    --output sarif --output-file-path "$OUT" --quiet --compact
  [[ -f "$OUT/results.sarif" ]] && mv "$OUT/results.sarif" "$OUT/checkov.sarif"
fi

echo
echo "=== results in $OUT ==="
ls -1 "$OUT"/*.sarif 2>/dev/null || echo "(no SARIF produced -- are any scanners installed?)"

if [[ "$FAIL_ON_CRITICAL" == "1" ]]; then
  if grep -qi '"level"[[:space:]]*:[[:space:]]*"error"' "$OUT"/*.sarif 2>/dev/null; then
    echo "error-level findings present; failing as requested" >&2
    exit 1
  fi
fi
exit 0