diff --git a/.github/workflows/apps/govulncheck-contribs-sarif.sh b/.github/workflows/apps/govulncheck-contribs-sarif.sh new file mode 100755 index 00000000000..dce2f49d03e --- /dev/null +++ b/.github/workflows/apps/govulncheck-contribs-sarif.sh @@ -0,0 +1,45 @@ +#!/bin/bash +set -euo pipefail + +# Scans each contrib module with govulncheck in SARIF format and merges the +# results into a single SARIF file for upload to GitHub Code Scanning. +# +# Usage: govulncheck-contribs-sarif.sh [output-file] +# output-file Path for the merged SARIF output (default: govulncheck-contribs.sarif) +# +# Requires: govulncheck, jq + +OUTPUT="${1:-govulncheck-contribs.sarif}" +SARIF_DIR=$(mktemp -d) +trap 'rm -rf "$SARIF_DIR"' EXIT + +count=0 +find ./contrib -mindepth 2 -type f -name go.mod -exec dirname {} \; | while read -r dir; do + echo "Scanning $dir" + # govulncheck requires at least one .go file in the target directory; + # fall back to the first subdirectory when the module root has none. + go_files=$(find "$dir" -maxdepth 1 -type f -name '*.go' | wc -l) + [[ $go_files -eq 0 ]] && dir=$(realpath "$(ls -d "$dir"/*/ | head -1)") + + safe_name=$(printf '%s' "$dir" | tr '/' '_' | sed 's/^_//') + # -format sarif exits 0 even when vulnerabilities are found. + govulncheck -format sarif -C "$dir" . >"$SARIF_DIR/${safe_name}.sarif" + count=$((count + 1)) +done + +sarif_files=("$SARIF_DIR"/*.sarif) +if [[ ! -e "${sarif_files[0]}" ]]; then + echo "No contrib modules found; skipping SARIF merge." + exit 0 +fi + +# Merge all per-module SARIF runs into one file. +# All runs share the same govulncheck schema version, so the first file's +# version and $schema fields are representative for the merged output. +jq -s '{ + "version": .[0].version, + "$schema": (.[0]."$schema" // ""), + "runs": [.[].runs[]] +}' "$SARIF_DIR"/*.sarif >"$OUTPUT" + +echo "Merged $(echo "$SARIF_DIR"/*.sarif | wc -w) SARIF files into $OUTPUT" diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index f7ff7ca5594..e7f9b390aa5 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -9,6 +9,7 @@ on: - "go.work.sum" - ".github/workflows/govulncheck.yml" - ".github/workflows/apps/govulncheck-contribs-v2.sh" + - ".github/workflows/apps/govulncheck-contribs-sarif.sh" workflow_call: # allows to reuse this workflow inputs: ref: @@ -42,11 +43,9 @@ jobs: # Replaces Dependabot Security Alerts with reachability-aware findings. # Uses the official golang/govulncheck-action — see PR description for # the enterprise allowlist request context. - # NOTE: Only core packages are scanned here. Contrib modules (each with - # their own go.mod) are scanned in govulncheck-tests, which blocks merges, - # but contrib vulnerabilities do not appear in GitHub Code Scanning alerts. - # TODO: extend SARIF upload to cover contrib modules for full Code Scanning - # visibility — requires multi-SARIF upload or a contrib-specific scan script. + # NOTE: Only core packages are scanned here. Contrib modules are scanned + # separately in govulncheck-contribs-analysis (SARIF, non-blocking) and + # in govulncheck-tests (blocking, sandboxed). govulncheck-analysis: runs-on: ubuntu-latest steps: @@ -71,6 +70,35 @@ jobs: sarif_file: govulncheck.sarif category: govulncheck + # Non-blocking: scans all contrib modules for vulnerabilities and uploads + # the merged SARIF to GitHub Code Scanning for Security tab visibility. + # Contrib vulns are also caught by govulncheck-tests (blocking, sandboxed). + govulncheck-contribs-analysis: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.ref || github.event.pull_request.head.sha || github.ref }} + persist-credentials: false + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version: stable + cache-dependency-path: '**/go.sum' + - name: Run govulncheck on contrib modules (SARIF) + # Installs govulncheck and runs govulncheck-contribs-sarif.sh, which + # scans each contrib module and merges results into one SARIF file. + # -format sarif exits 0 even when vulnerabilities are found. + run: | + go install golang.org/x/vuln/cmd/govulncheck@latest + ./.github/workflows/apps/govulncheck-contribs-sarif.sh govulncheck-contribs.sarif + - name: Upload contrib SARIF to GitHub Code Scanning + if: always() + uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + with: + sarif_file: govulncheck-contribs.sarif + category: govulncheck-contribs + # Blocking: fails the build if any reachable vulnerability is found. # Scans both core packages and all contrib modules (each with its own go.mod). # govulncheck execution is sandboxed via geomys/sandboxed-step (gVisor).