Skip to content

Commit 79ffcd3

Browse files
mcbenjemaawikkykclaudeCopilot
committed
ci: add govulncheck action
A govulncheck action with inline annotations and summary table. SARIF report uploaded on internal PRs and main to feed scan results into GitHub UI. Co-authored-by: Vic Kerr <wiktor.kerr@ionos.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent fad12c7 commit 79ffcd3

4 files changed

Lines changed: 111 additions & 0 deletions

File tree

.github/workflows/govulncheck.yml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: govulncheck
2+
on:
3+
pull_request: {}
4+
push:
5+
branches: [ "main" ]
6+
tags: [ "v*" ]
7+
8+
jobs:
9+
scan:
10+
runs-on: ubuntu-latest # govulncheck OOMs on ubuntu-slim
11+
permissions:
12+
contents: read
13+
steps:
14+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
15+
with:
16+
persist-credentials: false
17+
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
18+
with:
19+
go-version-file: go.mod
20+
- name: govulncheck
21+
run: go tool govulncheck -format sarif ./... >govulncheck.sarif
22+
- name: Annotate and summarise findings
23+
if: always()
24+
run: |
25+
if ! jq -e '.runs[0].results' govulncheck.sarif >/dev/null 2>&1; then
26+
echo '## govulncheck: no valid SARIF output produced' >>"$GITHUB_STEP_SUMMARY"
27+
exit 1
28+
fi
29+
findings=$(jq -r '
30+
( .runs[0].tool.driver.rules | INDEX(.id) |
31+
map_values({
32+
cve: (.properties.tags // [] | unique | map(select(startswith("CVE"))) | join(", ")),
33+
desc: .fullDescription.text
34+
})
35+
) as $rules |
36+
.runs[0].results[] |
37+
. as $r |
38+
(if $r.level == "warning" then "warning"
39+
elif $r.level == "note" then "notice"
40+
else "error" end) as $sev |
41+
($rules[$r.ruleId] // {cve:"",desc:""}) as $rule |
42+
if ($r.codeFlows | length) > 0 then
43+
$r.codeFlows[].threadFlows[0].locations |
44+
map(select(.location.physicalLocation.artifactLocation.uriBaseId == "%SRCROOT%")) |
45+
.[0].location.physicalLocation |
46+
[$sev, .artifactLocation.uri, (.region.startLine // 1 | tostring), $r.ruleId, $rule.cve, $rule.desc, $r.message.text] | @tsv
47+
else
48+
$r.locations[0].physicalLocation |
49+
[$sev, .artifactLocation.uri, (.region.startLine // 1 | tostring), $r.ruleId, $rule.cve, $rule.desc, $r.message.text] | @tsv
50+
end
51+
' govulncheck.sarif)
52+
esc() {
53+
local v=$1
54+
v=${v//'%'/'%25'}
55+
v=${v//$'\r'/'%0D'}
56+
v=${v//$'\n'/'%0A'}
57+
[ -z "$2" ] && v=${v//':'/'%3A'}
58+
[ -z "$2" ] && v=${v//','/'%2C'}
59+
printf '%s' "$v"
60+
}
61+
if [ -n "$findings" ]; then
62+
while IFS=$'\t' read -r sev file line ruleid cve desc msg; do
63+
echo "::$(esc "$sev") file=$(esc "$file"),line=$(esc "$line"),title=$(esc "$ruleid")::$(esc "$msg" 1)"
64+
done <<< "$findings"
65+
vulns=$(awk -F'\t' '!seen[$4]++' <<< "$findings")
66+
count=$(awk 'END{print NR}' <<< "$vulns")
67+
{
68+
echo "## govulncheck: $count vulnerability finding(s)"
69+
echo '| ID | CVE | Location | Severity | Details |'
70+
echo '|----|-----|----------|----------|---------|'
71+
while IFS=$'\t' read -r sev file line ruleid cve desc msg; do
72+
echo "| [${ruleid}](https://pkg.go.dev/vuln/${ruleid}) ${desc} | ${cve} | ${file}:${line} | ${sev} | ${msg} |"
73+
done <<< "$vulns"
74+
} >>"$GITHUB_STEP_SUMMARY"
75+
else
76+
echo '## govulncheck: no vulnerabilities found' >>"$GITHUB_STEP_SUMMARY"
77+
fi
78+
[ -n "$findings" ] && exit 1 || exit 0
79+
- if: always()
80+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
81+
with:
82+
name: govulncheck.sarif
83+
path: govulncheck.sarif
84+
85+
upload-sarif:
86+
needs: scan
87+
if: always() && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository)
88+
runs-on: ubuntu-slim
89+
permissions:
90+
security-events: write
91+
steps:
92+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
93+
with:
94+
name: govulncheck.sarif
95+
- name: Fix duplicate SARIF tags
96+
run: |
97+
jq '.runs[].tool.driver.rules |= map(if .properties != null and .properties.tags != null then .properties.tags |= unique else . end)' \
98+
govulncheck.sarif >govulncheck-fixed.sarif
99+
- uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
100+
with:
101+
sarif_file: govulncheck-fixed.sarif

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ verify-gen: generate manifests mockgen ## Verify go generated files and CRDs are
155155
echo "generated files are out of date, run make generate and/or make mockgen"; exit 1; \
156156
fi
157157

158+
.PHONY: govulncheck
159+
govulncheck: ## Run govulncheck to check for known vulnerabilities in the code.
160+
go tool govulncheck ./...
158161

159162
##@ Deployment
160163

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ tool (
4949
github.com/onsi/ginkgo/v2/ginkgo
5050
github.com/vektra/mockery/v2
5151
golang.org/x/tools/cmd/goimports
52+
golang.org/x/vuln/cmd/govulncheck
5253
k8s.io/code-generator/cmd/conversion-gen
5354
sigs.k8s.io/controller-runtime/tools/setup-envtest
5455
sigs.k8s.io/controller-tools/cmd/controller-gen
@@ -340,6 +341,7 @@ require (
340341
golang.org/x/term v0.43.0 // indirect
341342
golang.org/x/text v0.37.0 // indirect
342343
golang.org/x/time v0.11.0 // indirect
344+
golang.org/x/vuln v1.3.0 // indirect
343345
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
344346
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect
345347
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect

go.sum

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ github.com/google/cel-go v0.23.2 h1:UdEe3CvQh3Nv+E/j9r1Y//WO0K0cSyD7/y0bzyLIMI4=
353353
github.com/google/cel-go v0.23.2/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo=
354354
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
355355
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
356+
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=
357+
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
356358
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
357359
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
358360
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -376,6 +378,7 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI
376378
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
377379
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 h1:EwtI+Al+DeppwYX2oXJCETMO23COyaKGP6fHVpkpWpg=
378380
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
381+
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
379382
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
380383
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
381384
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
@@ -1019,6 +1022,8 @@ golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnps
10191022
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
10201023
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
10211024
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
1025+
golang.org/x/vuln v1.3.0 h1:hZYzR8uRhYhDSX88d+40TWbKAVw7BIvRWm26rtEn8jw=
1026+
golang.org/x/vuln v1.3.0/go.mod h1:MIY2PaR1y52stzZM3uHBboUAdVJvSVMl5nP3OQrwQaE=
10221027
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
10231028
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
10241029
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

0 commit comments

Comments
 (0)