Go modules remediation pull request development
- Status: Implemented (PR creation verified in a validation repository, and worker Pod operation verified in Kubernetes on a validation host).
- Started: October 29, 2026
- Last updated: October 30, 2026
Purpose
Extend language package remediation PRs, previously covering npm, pnpm, pip, and uv, to Go modules.
Create PRs that update go.mod and go.sum in mapped directories from findings that Trivy detects as gobinary in Go binaries in running images.
Approach
- Run the official
gocommand in a worker container, as with existing language packages - Treat worker container results as untrusted and validate them in KestreLynx
Decisions
Matching findings to binaries
- Only handle findings from binaries whose main module path matches the
modulein the mappedgo.mod - Findings from other Go tools included in the base image are excluded from remediation plans
- If a dependency version embedded in the binary does not match
require, require manual action
Findings in Go itself
- No PR is created for findings in the standard library, reported as
stdlib - They cannot be fixed by updating
go.mod - A separate remediation plan item explains that rebuilding with the specified Go version or later resolves them
Updates and the go directive
- Update all targets in a single
go getinvocation without runninggo mod tidy - The
godirective may be raised to the version declared in an updated module'sgo.mod - If the updated
godirective exceeds the Go version used to build the running binary, require manual action - Leave the decision to raise the Go version required for the build beyond the version the user is using to the user
When another target requires a higher version
- Omit the target for which a higher version is required by another target from the
go getarguments and let the dependency requirement raise its version - Specifying each target's exact fixed version in
go getfails when a new version of one target requires a higher version of another- For example,
golang.org/x/net v0.60.0requiresgolang.org/x/text v0.42.0, so the fixed version ofx/text,v0.41.0, cannot be specified at the same time
- For example,
- Validate the resulting version using the same checks as other accompanying updates
Versions used for validation
- Compare vulnerabilities before and after the update using the versions listed in the
requiredirectives ingo.mod - For example, in the PR used for this validation, compare
golang.org/x/net v0.20.0andgolang.org/x/text v0.14.0before the update withx/net v0.60.0andx/text v0.42.0after the update - As with npm and uv, compare module and vulnerability pairs
- Checking only the versions listed in
go.modis sufficient - With the default
-mod=readonlysetting,go builduses only the module versions listed ingo.mod - Verified with
go1.26.0that if a required module is missing fromgo.modor its listed version is lower than required, the build stops withupdates to go.mod neededwithout thegocommand selecting another version - Therefore, even if the working container returns an incomplete
go.mod, no unchecked versions enter the build; the build simply fails - Do not check versions found by following dependencies'
go.modfiles - Each module's
go.modalso requires older dependency versions, so following them collects many old versions that the build does not use - For example, even updating only
x/netfromv0.20.0tov0.23.0collected 37 versions, and 88 known vulnerabilities in unused versions, including a 2019 version ofgolang.org/x/cryptoandx/text v0.3.0, always required manual action - This validation assumes that users run
go buildwith its default settings - Running
go get,go mod tidy, or a build with-mod=modbefore the build causes thegocommand to select other versions, which falls outside the scope of this validation - The PR body states this assumption and includes
go build -mod=readonly ./... && go test -mod=readonly ./...to run in CI
Accompanying updates and go.sum
- Allow accompanying updates only if they can be reached by following requirements from the target fixed versions'
go.modfiles - Check
go.sumagainst records fromsum.golang.org - KestreLynx adds any missing lines and documents them in the PR body
Verification method
Unit tests
- Verified
go.modparsing and matching to binaries - Verified changes to the
godirective andgo.sumchecks - Verified explanations of accompanying updates and the PR body
Integration tests
Used local Docker with Go 1.26 and 1.27 from the official golang images, proxy.golang.org, sum.golang.org, and Trivy.
Verified updates to a module using golang.org/x/net v0.20.0 in five scenarios covering the following aspects.
- Updates to direct dependencies only
- Updates that also raise
golang.org/x/text - Updates that raise the
godirective from1.22to1.25.0 - Updates using Go 1.26 and Go 1.27 worker images
All five scenarios became PR candidates.
Real environment
Ran KestreLynx with local Docker against a Go application in a validation repository. Verified the workflow from remediation planning through GitHub PR creation.
| Item | Configuration |
|---|---|
| Go version used for the build | Go 1.26.10 |
| Modules used | golang.org/x/net v0.20.0 and golang.org/x/text v0.14.0 |
Verification results
The following results are from verification in a real environment on October 30, 2026.
Remediation plan and worker image
| Check | Result |
|---|---|
| Detected findings | Eight HIGH findings in golang.org/x/net (fixed versions from 0.23.0 to 0.60.0) and two findings in golang.org/x/text (fixed versions 0.39.0 and 0.41.0) |
| Target versions | x/net v0.60.0 and x/text v0.41.0 |
| Worker image | Selected golang1.26 (1.26.10) based on the input go directive and go 1.26.0 in the go.mod of x/net v0.60.0 |
PR changes and checks after the update
| Check | Result |
|---|---|
| PR creation | Created a GitHub PR in the validation repository from the remediation plan |
go directive in go.mod |
1.22 → 1.26.0 |
golang.org/x/net |
v0.20.0 → v0.60.0 |
golang.org/x/text |
v0.14.0 → v0.42.0 (// indirect) |
Reason for the x/text update |
The execution notes in the PR body explain why it was omitted from the go get arguments and updated to v0.42.0 through the requirement from x/net v0.60.0 |
go.sum |
Four lines added |
| Scans before and after the update | 10 resolved, 0 remaining, 0 new |
| Checks on the PR branch | go build -mod=readonly ./... and go vet -mod=readonly ./... passed, and the only versions used by the build were x/net v0.60.0 and x/text v0.42.0 |
Kubernetes worker Pods
| Check | Result |
|---|---|
| Worker Pod creation | Created language package update worker Pods in a worker namespace on K3s (v1.36.5) on a validation host, with the restricted Pod Security standard and an admission policy restricting worker Pod specifications applied |
| Go integration tests | Ran all five scenarios in worker Pods: updates to direct dependencies only, updates that also raise golang.org/x/text, updates that raise the go directive from 1.22 to 1.25.0, and updates using Go 1.26 and Go 1.27 worker images; all became PR candidates |
| Worker image operation | Official golang images pinned by digest (Go 1.26.10 and 1.27.3) ran in Pods with read-only root filesystems, completing go get and result retrieval |
| Worker Pods after completion | No completed worker Pods remained |
| Deployment of the version with Go support | Deployed to the production environment and the validation host; neither runs Go applications, so no actual Go updates have occurred yet |
Unverified areas and next steps
- Verification on arm64
- Verification of updates to Go applications in the production environment
Update history
October 29, 2026
- Implemented planning, updates, and PR creation, with integration tests.
October 30, 2026
- Verified PR creation in a real environment.
- Documented handling when another target requires a higher version.
- Verified Kubernetes worker Pod operation.
This article is a development record for KestreLynx. About KestreLynx