|
|
@@ -1,90 +1,120 @@
|
|
|
-#!/bin/bash
|
|
|
-# Audit dependencies for known vulnerabilities
|
|
|
-# Usage: ./dependency-audit.sh
|
|
|
+#!/usr/bin/env bash
|
|
|
+# Audit project dependencies with available ecosystem vulnerability scanners.
|
|
|
+#
|
|
|
+# Usage: dependency-audit.sh
|
|
|
+# Input: Project manifests in the current directory; no stdin input.
|
|
|
+# Output: Raw vulnerability scanner findings on stdout.
|
|
|
+# Stderr: Progress banners, missing-tool guidance, summaries, and usage errors.
|
|
|
+# Exit: 0 clean, 2 usage error, 10 findings present.
|
|
|
+#
|
|
|
+# Examples:
|
|
|
+# dependency-audit.sh
|
|
|
+# dependency-audit.sh > dependency-findings.txt
|
|
|
|
|
|
-set -e
|
|
|
+set -uo pipefail
|
|
|
+
|
|
|
+usage() {
|
|
|
+ cat <<'EOF'
|
|
|
+Usage: dependency-audit.sh
|
|
|
+
|
|
|
+Run available ecosystem vulnerability scanners for manifests in the current
|
|
|
+directory. Findings are written to stdout; progress is written to stderr.
|
|
|
+
|
|
|
+Exit codes:
|
|
|
+ 0 audits completed with no findings
|
|
|
+ 2 usage error
|
|
|
+ 10 one or more scanners reported findings
|
|
|
+
|
|
|
+EXAMPLES
|
|
|
+ dependency-audit.sh
|
|
|
+ dependency-audit.sh > dependency-findings.txt
|
|
|
+EOF
|
|
|
+}
|
|
|
+
|
|
|
+case "${1:-}" in
|
|
|
+ --help|-h) usage; exit 0 ;;
|
|
|
+ '') ;;
|
|
|
+ *) printf 'dependency-audit.sh: unknown argument: %s\n' "$1" >&2; usage >&2; exit 2 ;;
|
|
|
+esac
|
|
|
+if [[ $# -gt 1 ]]; then
|
|
|
+ printf 'dependency-audit.sh: expected no arguments\n' >&2
|
|
|
+ usage >&2
|
|
|
+ exit 2
|
|
|
+fi
|
|
|
|
|
|
RED='\033[0;31m'
|
|
|
-GREEN='\033[0;32m'
|
|
|
YELLOW='\033[1;33m'
|
|
|
NC='\033[0m'
|
|
|
+ISSUES=0
|
|
|
|
|
|
-echo "=== Dependency Security Audit ==="
|
|
|
-echo ""
|
|
|
+run_audit() {
|
|
|
+ if "$@"; then
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+ ISSUES=$((ISSUES + 1))
|
|
|
+ return 0
|
|
|
+}
|
|
|
|
|
|
-# Python
|
|
|
-if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
|
- echo "--- Python Dependencies ---"
|
|
|
+printf '%s\n\n' '=== Dependency Security Audit ===' >&2
|
|
|
|
|
|
- if command -v pip-audit &> /dev/null; then
|
|
|
- echo "Running pip-audit..."
|
|
|
- pip-audit || true
|
|
|
- elif command -v safety &> /dev/null; then
|
|
|
- echo "Running safety check..."
|
|
|
- safety check || true
|
|
|
+if [[ -f requirements.txt || -f pyproject.toml ]]; then
|
|
|
+ printf '%s\n' '--- Python Dependencies ---' >&2
|
|
|
+ if command -v pip-audit >/dev/null 2>&1; then
|
|
|
+ printf '%s\n' 'Running pip-audit...' >&2
|
|
|
+ run_audit pip-audit
|
|
|
+ elif command -v safety >/dev/null 2>&1; then
|
|
|
+ printf '%s\n' 'Running safety check...' >&2
|
|
|
+ run_audit safety check
|
|
|
else
|
|
|
- echo -e "${YELLOW}Install pip-audit or safety for Python vulnerability scanning${NC}"
|
|
|
- echo " pip install pip-audit"
|
|
|
+ printf '%bInstall pip-audit or safety for Python vulnerability scanning%b\n' "$YELLOW" "$NC" >&2
|
|
|
+ printf '%s\n' ' pip install pip-audit' >&2
|
|
|
fi
|
|
|
- echo ""
|
|
|
fi
|
|
|
|
|
|
-# Node.js
|
|
|
-if [ -f "package.json" ]; then
|
|
|
- echo "--- Node.js Dependencies ---"
|
|
|
-
|
|
|
- if command -v npm &> /dev/null; then
|
|
|
- echo "Running npm audit..."
|
|
|
- npm audit --audit-level=moderate || true
|
|
|
+if [[ -f package.json ]]; then
|
|
|
+ printf '%s\n' '--- Node.js Dependencies ---' >&2
|
|
|
+ if command -v npm >/dev/null 2>&1; then
|
|
|
+ printf '%s\n' 'Running npm audit...' >&2
|
|
|
+ run_audit npm audit --audit-level=moderate
|
|
|
fi
|
|
|
- echo ""
|
|
|
fi
|
|
|
|
|
|
-# Go
|
|
|
-if [ -f "go.mod" ]; then
|
|
|
- echo "--- Go Dependencies ---"
|
|
|
-
|
|
|
- if command -v govulncheck &> /dev/null; then
|
|
|
- echo "Running govulncheck..."
|
|
|
- govulncheck ./... || true
|
|
|
+if [[ -f go.mod ]]; then
|
|
|
+ printf '%s\n' '--- Go Dependencies ---' >&2
|
|
|
+ if command -v govulncheck >/dev/null 2>&1; then
|
|
|
+ printf '%s\n' 'Running govulncheck...' >&2
|
|
|
+ run_audit govulncheck ./...
|
|
|
else
|
|
|
- echo -e "${YELLOW}Install govulncheck for Go vulnerability scanning${NC}"
|
|
|
- echo " go install golang.org/x/vuln/cmd/govulncheck@latest"
|
|
|
+ printf '%bInstall govulncheck for Go vulnerability scanning%b\n' "$YELLOW" "$NC" >&2
|
|
|
+ printf '%s\n' ' go install golang.org/x/vuln/cmd/govulncheck@latest' >&2
|
|
|
fi
|
|
|
- echo ""
|
|
|
fi
|
|
|
|
|
|
-# Rust
|
|
|
-if [ -f "Cargo.toml" ]; then
|
|
|
- echo "--- Rust Dependencies ---"
|
|
|
-
|
|
|
- if command -v cargo-audit &> /dev/null; then
|
|
|
- echo "Running cargo audit..."
|
|
|
- cargo audit || true
|
|
|
+if [[ -f Cargo.toml ]]; then
|
|
|
+ printf '%s\n' '--- Rust Dependencies ---' >&2
|
|
|
+ if command -v cargo-audit >/dev/null 2>&1; then
|
|
|
+ printf '%s\n' 'Running cargo audit...' >&2
|
|
|
+ run_audit cargo audit
|
|
|
else
|
|
|
- echo -e "${YELLOW}Install cargo-audit for Rust vulnerability scanning${NC}"
|
|
|
- echo " cargo install cargo-audit"
|
|
|
+ printf '%bInstall cargo-audit for Rust vulnerability scanning%b\n' "$YELLOW" "$NC" >&2
|
|
|
+ printf '%s\n' ' cargo install cargo-audit' >&2
|
|
|
fi
|
|
|
- echo ""
|
|
|
fi
|
|
|
|
|
|
-# Docker
|
|
|
-if [ -f "Dockerfile" ]; then
|
|
|
- echo "--- Docker Image ---"
|
|
|
-
|
|
|
- if command -v trivy &> /dev/null; then
|
|
|
- echo "Running trivy on Dockerfile..."
|
|
|
- trivy config Dockerfile || true
|
|
|
+if [[ -f Dockerfile ]]; then
|
|
|
+ printf '%s\n' '--- Docker Image ---' >&2
|
|
|
+ if command -v trivy >/dev/null 2>&1; then
|
|
|
+ printf '%s\n' 'Running trivy on Dockerfile...' >&2
|
|
|
+ run_audit trivy config Dockerfile
|
|
|
else
|
|
|
- echo -e "${YELLOW}Install trivy for container vulnerability scanning${NC}"
|
|
|
- echo " brew install trivy"
|
|
|
+ printf '%bInstall trivy for container vulnerability scanning%b\n' "$YELLOW" "$NC" >&2
|
|
|
+ printf '%s\n' ' brew install trivy' >&2
|
|
|
fi
|
|
|
- echo ""
|
|
|
fi
|
|
|
|
|
|
-echo "=== Audit Complete ==="
|
|
|
-echo ""
|
|
|
-echo "Recommended actions:"
|
|
|
-echo "1. Update vulnerable packages to patched versions"
|
|
|
-echo "2. Review advisories for workarounds if updates unavailable"
|
|
|
-echo "3. Consider alternative packages for unmaintained dependencies"
|
|
|
+printf '%s\n' '=== Audit Complete ===' >&2
|
|
|
+if [[ $ISSUES -gt 0 ]]; then
|
|
|
+ printf '%bOne or more dependency scanners reported findings%b\n' "$RED" "$NC" >&2
|
|
|
+ exit 10
|
|
|
+fi
|
|
|
+exit 0
|