#!/usr/bin/env bash # VajraShield CBOM — safe repository zip export for static assessment. # Moat: we own intake quality; clients get the same script we use in pilots. # Also copied to .github/actions/cbom-export/ for the composite GitHub Action. # # Usage: # ./scripts/vajra_export_zip.sh [REPO_ROOT] [OUTPUT_ZIP] # ./scripts/vajra_export_zip.sh . ./acme-payments-cbom.zip # # Limits (pilot): 25 MB zip — aligns with api scanner upload default. set -euo pipefail ROOT="$(cd "${1:-.}" && pwd)" OUT="${2:-vajra-cbom-export.zip}" MAX_BYTES=$((25 * 1024 * 1024)) SECRET_HINTS=( ".env" ".env.local" ".env.production" "id_rsa" "id_ed25519" "*.pem" "*.p12" "*.pfx" "credentials.json" "service-account.json" ) LOCKFILES=( "package-lock.json" "yarn.lock" "pnpm-lock.yaml" "requirements.txt" "Pipfile.lock" "poetry.lock" "go.sum" "pom.xml" "build.gradle" "Cargo.lock" ) echo "=== VajraShield CBOM export ===" echo "Root: $ROOT" echo "Output: $OUT" echo "" if [[ ! -d "$ROOT" ]]; then echo "ERROR: not a directory: $ROOT" >&2 exit 1 fi # Warn on secret-like paths (do not fail — client may have empty placeholders) echo "--- Secret filename check (warnings only) ---" found_secret=0 while IFS= read -r -d '' path; do base="$(basename "$path")" for hint in "${SECRET_HINTS[@]}"; do case "$base" in $hint) echo "WARN: possible secret file: ${path#$ROOT/}" found_secret=1 ;; esac done done < <(find "$ROOT" -type f \( \ -name '.env' -o -name '.env.*' -o -name '*.pem' -o -name '*.p12' -o -name '*.pfx' \ -o -name 'credentials.json' -o -name 'service-account.json' -o -name 'id_rsa' -o -name 'id_ed25519' \ \) -print0 2>/dev/null || true) if [[ "$found_secret" -eq 0 ]]; then echo "OK: no common secret filenames detected" fi echo "" echo "--- Lockfiles ---" lock_found=0 for name in "${LOCKFILES[@]}"; do while IFS= read -r -d '' f; do echo " ✓ ${f#$ROOT/}" lock_found=1 done < <(find "$ROOT" -name "$name" -type f -print0 2>/dev/null || true) done if [[ "$lock_found" -eq 0 ]]; then echo "WARN: no standard lockfiles found — dependency audit may be limited" fi echo "" rm -f "$OUT" if git -C "$ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then echo "--- Export via git archive (tracked files only) ---" ref="HEAD" if ! git -C "$ROOT" rev-parse "$ref" >/dev/null 2>&1; then echo "ERROR: git repo has no commits on HEAD" >&2 exit 1 fi git -C "$ROOT" archive --format=zip --output="$OUT" "$ref" else echo "--- Export via zip (untracked tree) ---" ( cd "$ROOT" zip -qr "$OUT" . \ -x '*/.git/*' -x '*/node_modules/*' -x '*/vendor/*' \ -x '*/dist/*' -x '*/build/*' -x '*/.venv/*' -x '*/__pycache__/*' ) fi size="$(wc -c <"$OUT" | tr -d ' ')" echo "" echo "Created: $OUT ($size bytes)" if [[ "$size" -gt "$MAX_BYTES" ]]; then echo "WARN: zip exceeds ${MAX_BYTES} bytes (25 MB pilot limit)." echo " Split by service/repo or add .vajra-cbom-ignore and re-export." exit 2 fi echo "OK: ready for secure transfer to VajraShield" exit 0