Safeguard
Developer Tools•

Exclude, replace or upgrade: how to fix a vulnerable Go transitive module

To fix a vulnerable transitive Go module, require the fixed version directly. exclude only blocks a version, and replace skips authentication.

Safeguard Security Team
3 min read

The cleanest fix is to require the fixed version yourself with go get module@fixedversion. Minimal version selection then picks it for the whole build. Use exclude rarely, since it only blocks one version, and use replace only for a reviewed fork, because Go does not authenticate replaced modules.

Why upgrading works in Go

Go builds with the highest version any module in the graph requires. If a dependency asks for an old, vulnerable version of a library, you can add your own requirement on a newer one and the newer version wins. The Go supply chain article describes builds as locked by the main module's go.mod, so your requirement decides.

What exclude does

The Go reference says exclude prevents a module version from being loaded. It applies only in the main module's go.mod. Since Go 1.16, the excluded requirement is ignored, which can lead go get or go mod tidy to add a higher version. Before 1.16, the next higher non excluded version was loaded.

So exclude can work, but it is a blunt tool: it names what you do not want, not what you do. A direct requirement states the version you do want.

What replace does

Replace points a module at another path or version. The managing dependencies guide warns that Go tools do not authenticate external modules you replace. It is the right tool for a fork you maintain, not for routine fixes. See the replace directive.

Decision table

SituationBest option
A fixed release existsgo get module@fixed, then tidy
Parent module pins the old version and is maintainedUpgrade the parent, then drop your override
No fixed release, a patched fork existsreplace to a pinned tag of the fork, review it
A single bad version must never loadexclude, plus a direct requirement on a good one

Steps

  1. Identify the path with go mod why -m and go mod graph. See finding who pulls a dependency.
  2. Run go get example.com/lib@v1.4.2, where v1.4.2 is the fixed release.
  3. Run go mod tidy and read the diff.
  4. Run go list -m example.com/lib to confirm the selected version.
  5. Test, rescan and note in the pull request which parent module caused the issue.
  6. When the parent updates, remove your direct requirement if the code does not import the library itself, and tidy again.

Try it yourself

Click through it at your own pace, or open it full screen. Look at how the fixed version is chosen and which files change.

Where Safeguard fits

Safeguard offers autonomous remediation with fix pull requests, off by default with every category on Manual. Dependency scanning is available through a free scan.

Quick check

Does exclude affect people who import my module?

No. Exclude only applies in the main module's go.mod and is ignored in other modules.

Why does go mod tidy sometimes add a higher version after exclude?

Since Go 1.16 an excluded requirement is ignored, so the go command may add a higher version.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.