This content originally appeared on DEV Community and was authored by Oleg Sydorov
Today, I want to talk about addressing vulnerabilities in our Go projects. As you may know, the standard tool for vulnerability checking is govulncheck, an official utility from the Go development team that leverages the Go Vulnerability Database. In addition to being used as a standalone tool, this utility is integrated into GoLand IDE starting from version 2023.1, enabling real-time scanning of the go.mod file. Of course, you can always run govulncheck manually as well.
At first glance, it seems straightforward — what could possibly go wrong? Imagine you finish working on your code, run govulncheck, and confidently commit your changes. Suddenly, your CI/CD pipeline fails to build or, worse, your IT security team escalates an issue. You’re puzzled: how is this possible?
The nuance here lies in the fact that govulncheck only checks and considers effective dependencies, i.e., those actually used by the code. In contrast, many scanners commonly integrated into pipelines — such as Trivy, Grype, or platforms like Sonatype IQ (Nexus Lifecycle) — often operate in a “paranoid” mode, scanning the entire dependency graph, including unused or transitive packages. This frequently leads to situations where seemingly clean code triggers multiple vulnerability alerts.
Let’s look at the detailed report (Sonatype OSS index example)
Let’s turn to our go.mod file.
module my-awesome-project
go 1.23.0
toolchain go1.23.9
require (
github.com/aws/aws-cdk-go/awscdk/v2 v2.204.0
github.com/aws/aws-cdk-go/awscdklambdagoalpha/v2 v2.204.0-alpha.0
github.com/aws/aws-lambda-go v1.49.0
github.com/aws/constructs-go/constructs/v10 v10.4.2
github.com/aws/jsii-runtime-go v1.112.0
)
require (
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 v2.2.244 // indirect
github.com/cdklabs/awscdk-asset-node-proxy-agent-go/nodeproxyagentv6/v2 v2.1.0 // indirect
github.com/cdklabs/cloud-assembly-schema-go/awscdkcloudassemblyschema/v44 v44.9.0 // indirect
github.com/cdklabs/cloud-assembly-schema-go/awscdkcloudassemblyschema/v45 v45.2.0 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/yuin/goldmark v1.7.12 // indirect
golang.org/x/lint v0.0.0-20241112194109-818c5a804067 // indirect
golang.org/x/mod v0.26.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/tools v0.35.0 // indirect
)
What do we see? Our project does not have the problems reported by the scanner! However, as soon as you follow go mod graph | grep ….some_bad_package command, the situation immediately changes: the secret becomes clear.
Let’s look at the detailed report again. Let’s take a closer look at the particular vulnerability that was discovered.
The scanner complains about version 2.2.240 and recommends replacing it with a version no lower than 2.2.242
Well, now let’s turn to the go.sum file. Maybe the answer lies here?
Excellent! So, the crime is solved.
But how can this be addressed? The solution is as follows: You need to use the replace directive to override vulnerable packages with safe versions directly in your go.mod file.
In our case (see the full list of the detected vulnerabilities above), we will apply to the go.mod file such a fix:
replace (
github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 => github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 v2.2.244
github.com/golang-jwt/jwt/v5 => github.com/golang-jwt/jwt/v5 v5.2.2
golang.org/x/crypto => golang.org/x/crypto v0.38.0
golang.org/x/net => golang.org/x/net v0.40.0
golang.org/x/text => golang.org/x/text v0.25.0
)
I recommend exercising caution:
Ensure compatibility and correct versioning with your Go environment
Verify that your code still builds successfully after the change
After applying the fix, run go mod tidy and, if needed, go mod vendor to clean up and update your module dependencies accordingly.
The results were not long in coming:
Likewise, the rest of the packages such as crypto, text, net, etc. also have been fixed.
Thus, as we’ve seen, the problem runs deeper and its resolution cannot be fully achieved using only standard methods and tools.
Wishing you successful development and clean code!
This content originally appeared on DEV Community and was authored by Oleg Sydorov