|
| 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 |
0 commit comments