A replace directive is safe when you treat it as a reviewed exception. It redirects a Go module to a fork or local folder, and the Go documentation warns that Go tools do not authenticate external modules you replace. It applies only in your main module, so it never travels to your users.
What replace does
The replace line in go.mod maps a module path, optionally with a version, to another module path or a local directory. The Go reference gives these rules:
- It only applies in the main module's go.mod and is ignored in other modules.
- With a version on the left, only that version is replaced. Without one, all versions are.
- A local path on the right must begin with
./or../. - A replace alone does not add a module to the graph. A matching
requireis also needed.
A fork replacement looks like this:
replace example.com/theirmodule v1.2.3 => example.com/myfork/theirmodule v1.2.3-fixed
The security trade
The managing dependencies guide says plainly: "When you use the replace directive, Go tools don't authenticate external modules." Normal modules are checked against the checksum database. A replaced one is whatever your fork or folder contains at build time.
For a local path that means the code is not even versioned. Two developers can build different things from the same commit.
| Replacement | Main risk | Mitigation |
|---|---|---|
| Local path | Unversioned code in the build | Never merge to the release branch |
| Fork at a tag | Fork drifts from upstream fixes | Track upstream, set a review date |
| Fork on a personal account | Account or repo changes | Host forks in your own organization |
Steps to use replace responsibly
- Add a comment above the line stating why, who owns it and when to remove it.
- Prefer forks in an organization you control over personal repositories.
- Pin the fork to a tag or pseudo-version, not a moving branch.
- Open the upstream pull request, then delete the replace when the fix ships.
- Add a CI check that fails if a local path replace is present on a release branch.
A simple grep in CI works: search go.mod for lines containing => ./ or => ../.
Why it does not protect your users
Because replace is ignored outside the main module, a library author cannot ship a fork fix to consumers through it. Consumers need to add their own replace or you need to publish a new version. Remember this when you read a library's go.mod: a replace there tells you nothing about what your build uses.
Where Safeguard fits
Safeguard's dependency scanning reads the module graph and flags known vulnerabilities, and policy gates can block merges when findings cross a threshold. A free scan shows what your current go.mod resolves to.
Quick check
Does replace in a dependency's go.mod affect my build?
No. Replace directives only apply in the main module's go.mod and are ignored in other modules.
Is a replaced module checked against the checksum database?
The Go guide says Go tools do not authenticate external modules when you use replace, so review the source yourself.
Sources
Last reviewed: 19 October 2026.