Visibility internal Owner _ Approver _ Created _ Updated _
scan-static.sh
| Field | Value |
|---|---|
| Type | Shell |
| Source | Forge/Skills/Security_Scan/scripts/scan-static.sh |
| Parent | Forge |
| GitHub | Forge/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