From a365238854e916d0110ceb6f68cdcb7ccf25373a Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 17 Jun 2026 20:06:02 +0200 Subject: [PATCH] .github: scan Go modules for known vulnerabilities Add govulncheck CI and Dependabot for the two Go modules, src/webui and src/netbrowse, so vendored dependencies don't quietly accumulate CVEs between manual updates. The workflow reports every finding in the run summary but only fails on vulnerabilities our code actually calls in a dependency. Called stdlib vulnerabilities are surfaced too, but they're fixed by bumping the Buildroot host Go rather than a module's go.mod, so they don't gate the build. Dependabot ignores openconfig/goyang: it's pinned to our kernelkit fork via a replace directive and stepped by hand. Signed-off-by: Joachim Wiberg --- .github/dependabot.yml | 15 +++++++ .github/workflows/govulncheck.yml | 68 +++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/govulncheck.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..075307de --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +version: 2 +updates: + - package-ecosystem: gomod + directory: /src/webui + schedule: + interval: weekly + # goyang is pinned to our kernelkit fork via a replace directive and + # stepped by hand when we add patches; leave it for Dependabot to ignore. + ignore: + - dependency-name: github.com/openconfig/goyang + + - package-ecosystem: gomod + directory: /src/netbrowse + schedule: + interval: weekly diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml new file mode 100644 index 00000000..8fcc6b24 --- /dev/null +++ b/.github/workflows/govulncheck.yml @@ -0,0 +1,68 @@ +name: Go Vulnerability Scan + +on: + push: + branches: + - main + paths: + - 'src/webui/**' + - 'src/netbrowse/**' + - '.github/workflows/govulncheck.yml' + pull_request: + paths: + - 'src/webui/**' + - 'src/netbrowse/**' + - '.github/workflows/govulncheck.yml' + schedule: + - cron: '5 0 * * 6' # Saturday at 00:05 UTC, same as Coverity + workflow_dispatch: + +jobs: + govulncheck: + if: ${{ github.repository_owner == 'kernelkit' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + module: + - src/webui + - src/netbrowse + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-go@v6 + with: + go-version: stable + + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@latest + + - name: Scan ${{ matrix.module }} + working-directory: ${{ matrix.module }} + run: | + # Full report, for the run summary. govulncheck exits non-zero + # whenever it finds anything, so don't let it fail the step here. + { + echo "## govulncheck: ${{ matrix.module }}" + echo '```' + govulncheck ./... || true + echo '```' + } | tee -a "$GITHUB_STEP_SUMMARY" + + # Gate on vulnerabilities reachable from our code through a + # dependency. govulncheck's call-graph analysis is transitive, + # so indirect use counts too (we call a dep that calls the bad + # symbol). trace[0] is the vulnerable symbol; we key on the + # module it lives in. A chain that bottoms out in stdlib is + # fixed by bumping the Buildroot host Go, not this module's + # go.mod, so it's reported above but doesn't fail the build. + # Keep the json scan and jq unguarded so a tool failure fails the + # gate closed; only grep's no-match exit (all-clear) is tolerated. + govulncheck -format json ./... > scan.json || true + called=$(jq -r 'select(.finding.trace[0].function != null) | + .finding.trace[0].module' scan.json | sort -u) + vulns=$(printf '%s' "$called" | grep -vx stdlib || true) + if [ -n "$vulns" ]; then + echo "::error::Called vulnerabilities in dependencies: $(echo "$vulns" | paste -sd, -)" + exit 1 + fi