| # ============================================================================= | |
| # Container Security Scan Pipeline — Trivy + Grype + Dockle | |
| # ============================================================================= | |
| set -euo pipefail | |
| IMAGE="${1:?Usage: $0 <image>}" | |
| REPORT_DIR="${REPORT_DIR:-./scan-reports}" | |
| SEVERITY="${SEVERITY:-CRITICAL,HIGH}" | |
| EXIT_ON_CRITICAL="${EXIT_ON_CRITICAL:-true}" | |
| mkdir -p "${REPORT_DIR}" | |
| echo "=== Scanning ${IMAGE} ===" | |
| # --- Trivy: Vulnerability Scan --- | |
| echo "[1/4] Trivy vulnerability scan..." | |
| trivy image \ | |
| --severity "${SEVERITY}" \ | |
| --format json \ | |
| --output "${REPORT_DIR}/trivy-vuln.json" \ | |
| --exit-code 0 \ | |
| "${IMAGE}" | |
| trivy image \ | |
| --severity "${SEVERITY}" \ | |
| --format table \ | |
| "${IMAGE}" | |
| # --- Trivy: Misconfiguration Scan --- | |
| echo "[2/4] Trivy misconfig scan..." | |
| trivy config \ | |
| --severity "${SEVERITY}" \ | |
| --format json \ | |
| --output "${REPORT_DIR}/trivy-misconf.json" \ | |
| . | |
| # --- Trivy: Secret Scan --- | |
| echo "[3/4] Trivy secret scan..." | |
| trivy fs \ | |
| --scanners secret \ | |
| --format json \ | |
| --output "${REPORT_DIR}/trivy-secrets.json" \ | |
| . | |
| # --- Trivy: SBOM Generation --- | |
| echo "[4/4] Generating SBOM..." | |
| trivy image \ | |
| --format spdx-json \ | |
| --output "${REPORT_DIR}/sbom.spdx.json" \ | |
| "${IMAGE}" | |
| # --- Check for Critical CVEs --- | |
| CRITICAL_COUNT=$(jq '[.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL")] | length' "${REPORT_DIR}/trivy-vuln.json") | |
| echo "Critical vulnerabilities: ${CRITICAL_COUNT}" | |
| if [[ "${EXIT_ON_CRITICAL}" == "true" && "${CRITICAL_COUNT}" -gt 0 ]]; then | |
| echo "FAIL: Critical vulnerabilities found — blocking deployment" | |
| exit 1 | |
| fi | |
| echo "=== Scan complete ===" | |