Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: run govulncheck with go version from build image #2931

Merged
merged 4 commits into from
Jul 15, 2024

Conversation

hairyhum
Copy link
Contributor

@hairyhum hairyhum commented Jun 10, 2024

Change Overview

Patch Go version from cache might contain vulnerabilities, but we specify minor version only in go.mod file.

Pull request type

Please check the type of change your PR introduces:

  • 🚧 Work in Progress
  • 🌈 Refactoring (no functional changes, no api changes)
  • 🐹 Trivial/Minor
  • 🐛 Bugfix
  • 🌻 Feature
  • 🗺️ Documentation
  • 🤖 Test
  • 🏗️ Build

Issues

Test Plan

Run the workflow from this branch

  • 💪 Manual
  • ⚡ Unit test
  • 💚 E2E

@infraq infraq added this to In Progress in Kanister Jun 10, 2024
@hairyhum
Copy link
Contributor Author

Copy link
Contributor

@psilva-veeam psilva-veeam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the Go version in vulncheck should be the same as used. It's also possible to define a Go version explicitly in the yaml file, so that they a synchronous

Kanister automation moved this from In Progress to Review Required Jun 13, 2024
@psilva-veeam
Copy link
Contributor

So instead go-version-input should be set https://github.com/golang/govulncheck-action/blob/dd0578b371c987f96d1185abb54344b44352bd58/action.yml#L4. Another option is setting go-version-file https://github.com/golang/govulncheck-action/blob/master/action.yml#L4 i.e. the synchronization is always there and only go.mod would have to be adapted during new Go releases

@psilva-veeam
Copy link
Contributor

Patch Go version from cache might contain vulnerabilities, but we specify minor version only in go.mod file.

Actually recent Go releases automatically also specify the patch version in go.mod. I've seen this e.g. recently when using go mod tidy

@hairyhum
Copy link
Contributor Author

Actually recent Go releases automatically also specify the patch version in go.mod. I've seen this e.g. recently when using go mod tidy

When I run go mod tidy in kanister with 1.22.4 it doesn't do that.

Well the Go version in vulncheck should be the same as used. It's also possible to define a Go version explicitly in the yaml file, so that they a synchronous

"Used" version is whatever we have in the build image https://github.com/kanisterio/kanister/blob/master/docker/build/Dockerfile#L1
The reason we specify the minor version is because we don't want to bump the patch version in the code all the time. At the same time we don't rebuild the build image that often, so maybe having patch version in the go.mod is a good idea.

Alternatively we might consider using github workflow tools instead of the build image, maybe.

@psilva-veeam
Copy link
Contributor

Actually recent Go releases automatically also specify the patch version in go.mod. I've seen this e.g. recently when using go mod tidy

When I run go mod tidy in kanister with 1.22.4 it doesn't do that.

Well the Go version in vulncheck should be the same as used. It's also possible to define a Go version explicitly in the yaml file, so that they a synchronous

"Used" version is whatever we have in the build image https://github.com/kanisterio/kanister/blob/master/docker/build/Dockerfile#L1 The reason we specify the minor version is because we don't want to bump the patch version in the code all the time. At the same time we don't rebuild the build image that often, so maybe having patch version in the go.mod is a good idea.

Wouldn't it be easier at this point to install and run govulncheck directly instead of using the Github Action? E.g.:

go install golang.org/x/vuln/cmd/govulncheck@3740f5cb12a3f93b18dbe200c4bcb6256f8586e2
govulncheck ./...

This way it's guaranteed that the check against the Go standard library version is always the same as in the build image. That's especially useful for minor version upgrades that need to be postponed. Another advantage is that this would allow for version pinning. This would create fully reproducible results and is also a security recommendation. [1] (The govulncheck action always pulls latest [2])

[1] OpenSSF Scorecard / Check Documentation / Pinned-Dependencies
[2] https://github.com/golang/govulncheck-action/blob/master/action.yml

Alternatively we might consider using github workflow tools instead of the build image, maybe.

Ah ok, what would be the difference for that option?

@psilva-veeam
Copy link
Contributor

psilva-veeam commented Jun 14, 2024

(Arguably checking a commit from a year ago with latest might be more useful than checking with known vulnerabilities from a year ago. I guess there's no strict right or wrong. On the other hand I still wonder what happens when a newer Go version needs to be held back while govulncheck blindly assumes the patched version is used

So maybe

go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...

might provide the best trade-offs)

@hairyhum
Copy link
Contributor Author

Wouldn't it be easier at this point to install and run govulncheck directly instead of using the Github Action?

That also makes sense. Then we will need to bump the go version in the build image if we have vulnerability report. That streamlines the process a bit.

@@ -23,3 +23,4 @@ jobs:
repo-checkout: false
cache: false
go-version-file: go.mod
check-latest: true
Copy link
Contributor

@julio-lopez julio-lopez Jun 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@psilva-veeam IIUC, the line above (25) makes it so the Go version used to run govulncheck matches the one used to build the code up to the minor version, but maybe not the patch version since it is not (currently) specified in the go.mod file.

Is this your understanding as well? Is that sufficient or is there a need to run with the specific patch version?

Also, the go.mod file specifies the toolchain with a patch version, perhaps that needs to be updated?
The go version used by govulncheck is whatever the actions/setup-go action downloads. It is not clear whether or not it uses the toolchain entry from the go.mod file. I didn't see it described in the documentation, but that is easy to test.

@hairyhum How does check-latest: interact or change the behavior of go-version-file: go.mod ?

https://github.com/actions/setup-go?tab=readme-ov-file#check-latest-version

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@julio-lopez I think so, this is also my understanding. So I've been running quite a few tests with govulncheck when it was added. What I noticed is that the difference in patch versions produces occasional warnings. Especially in net and net/http, e.g. the HTTP/2 bug that was fixed in go1.21.9 and 1.22.1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I think I have a better understanding now. These warning are specific to vulnerabilities detected in the standard library.

Does this comment describe the risk?
#2931 (comment)

@hairyhum
Copy link
Contributor Author

Also, the go.mod file specifies the toolchain with a patch version, perhaps that needs to be updated?

Yes, updating the toolchain setting to 1.22.4 makes the govulnchech pass.

But I'm not 100% sure that's the right way to go, because if we build the binaries with make build-controller or make goreleaser we get them built with the go version from the build image (which is 1.22.2 currently)

So I feel like we better either keep go version in go.mod in sync with the build image or use the build image to run govulncheck instead of govulncheck action.

@julio-lopez
Copy link
Contributor

Also, the go.mod file specifies the toolchain with a patch version, perhaps that needs to be updated?

Yes, updating the toolchain setting to 1.22.4 makes the govulnchech pass.

But I'm not 100% sure that's the right way to go, because if we build the binaries with make build-controller or make goreleaser we get them built with the go version from the build image (which is 1.22.2 currently)

My understanding, (and please verify because I could be wrong) is that the Go toolchain will attempt to use the newer toolchain when the version of the currently running toolchain does not match.

From the "Go Toolchains" documentation:

The choice of Go toolchain being used depends on the GOTOOLCHAIN environment setting and the go and toolchain lines in the main module’s go.mod file or the current workspace’s go.work file.
...
In the standard configuration, the go command uses its own bundled toolchain when that toolchain is at least as new as the go or toolchain lines in the main module or workspace. For example, when using the go command bundled with Go 1.21.3 in a main module that says go 1.21.0, the go command uses Go 1.21.3.

When the go or toolchain line is newer than the bundled toolchain, the go command runs the newer toolchain instead. For example, when using the go command bundled with Go 1.21.3 in a main module that says go 1.21.9, the go command finds and runs Go 1.21.9 instead.

Having said that, if this ends up downloading the new toolchain every time, we might as well upgrade the local version of Go.

It appears that there is a risk in not upgrading Go.

@julio-lopez
Copy link
Contributor

@hairyhum

So I feel like we better either keep go version in go.mod in sync with the build image or use the build image to run govulncheck instead of govulncheck action.

IIUC, the risk would be to incorrectly deem a build as non-vulnerable when there is an actual vulnerability. Is that the concern?

The scenario would be:

  • Run govulncheck with the most recent Go toolchain, which would cause the check to "incorrectly" succeed.
  • And then build the rest of the code with an outdated Go toolchain that has known vulnerabilities (for example, in the standard library).

@@ -2,7 +2,7 @@ module github.com/kanisterio/kanister

go 1.22

toolchain go1.22.2
toolchain go1.22.4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would address the most recent vulnerabilities flagged by govulncheck.

Does it does address the risk described in this comment?

@hairyhum
Copy link
Contributor Author

My understanding, (and please verify because I could be wrong) is that the Go toolchain will attempt to use the newer toolchain when the version of the currently running toolchain does not match.

Not unless there's a GOTOOLCHAIN variable set in the environment. And it is set in the golang:1.22-bullseye which we base the build image from.
This makes sense for the build image for predictability reasons. You don't want the build image to auto-detect and download a new golang version.

Unfortunately it doesn't fail or warn us the the toolchain is set to later version than the local and just builds with whatever it currently has.

If we set go 1.22.4 in go.mod file, it would fail then. So I would suggest that we do that and keep our build image up to date.

Kanister automation moved this from Review Required to Reviewer approved Jun 21, 2024
@hairyhum hairyhum force-pushed the govulncheck-check-latest-go-version branch from 098d765 to e231620 Compare June 21, 2024 18:06
Go version from the code might be resolved differently, we build packages
using build image local toolchain.

Make workflow resolve latest build image version for govulncheck
@hairyhum hairyhum force-pushed the govulncheck-check-latest-go-version branch from e231620 to 3a56e79 Compare June 21, 2024 19:50
@hairyhum
Copy link
Contributor Author

REWORK

The PR now gets go version from the build image.

@hairyhum hairyhum changed the title build: run govulncheck with latest supported go version build: run govulncheck with go version from build image Jun 21, 2024
@hairyhum hairyhum added the kueue label Jun 27, 2024
@@ -15,11 +15,16 @@ jobs:
steps:
- name: 'Checkout Repository'
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: 'Get go version from build image'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add a comment that makes it explicit that this is used in the next step to specify the Go version to use. It is easy to miss the connection (via ${{ steps.go_version.outputs.go_version }}) when going through the workflow.

@hairyhum hairyhum merged commit e768225 into master Jul 15, 2024
16 of 17 checks passed
Kanister automation moved this from Reviewer approved to Done Jul 15, 2024
@hairyhum hairyhum deleted the govulncheck-check-latest-go-version branch July 15, 2024 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

Successfully merging this pull request may close these issues.

None yet

3 participants