Safeguard
Developer Tools•

How do Go vendor directories affect scanner onboarding in a monorepo?

A Go vendor directory holds copied dependencies inside the repository. Learn how to check it matches go.mod, scan it once, and avoid double counting.

Safeguard Security Team
3 min read

A vendor directory holds copies of a Go module's dependencies inside the repository, so builds can run without fetching them. When onboarding a scanner, confirm that vendor matches go.mod and go.sum, scan one source of truth, and avoid counting the same package twice.

What the vendor directory is

The Go modules reference describes vendoring as keeping dependency copies in a vendor directory created by the go mod vendor command, with a vendor/modules.txt file that records what was copied. It also says that automatic vendoring may be enabled when the go version in go.mod is 1.14 or higher and the vendor directory exists, so the build may use the copies without any extra flag.

That has a direct consequence for security tooling. What the compiler uses can be the vendor copy, not what go.mod says it resolves online.

Why this matters at onboarding

  • If vendor and go.mod disagree, the build uses vendor, and a scan of go.mod alone is wrong.
  • If you scan both, every package may appear twice, once as a dependency and once as files.
  • A vendored package can be edited by hand. Then it is no longer the published version, and a scanner matching on version number may miss or misjudge it.

Checks to run

  1. Find every go.mod in the monorepo. Large repositories often have many modules, or a single go.work file tying several together.
  2. For each module, check whether a vendor directory exists beside it.
  3. Compare the packages in vendor/modules.txt with go.mod. Differences mean the vendor copy is stale or was edited.
  4. Search vendored directories for local changes by comparing against a fresh download of the same version.
  5. Choose the scan source: for built services, usually go.mod plus go.sum; add a vendor check as a second pass.

Decision table

ConditionScan sourceExtra step
vendor matches modules.txt and go.modgo.mod and go.sumNone
vendor older than go.modvendor, as that is what buildsPlan a refresh
Hand edited vendored packageMark as modifiedReview by a developer
No vendor directorygo.mod and go.sumNone

Refreshing vendor safely

When you refresh a vendor directory, the pull request is large. Reviewers cannot read thousands of changed lines, so make the pull request contain only the refresh, and add a short note listing versions that changed. Run the full test suite. Keep security fixes and refreshes in separate changes so a rollback is clean.

Keep one number

Tell stakeholders how you count. Say "we count packages from go.mod, and use vendor only to confirm it" and stick to it. Switching counting rules between reports makes trends meaningless.

Where Safeguard fits

Safeguard's dependency scanning and SBOM output cover Go modules, and reachability analysis can help show whether a vulnerable function is called. The CLI 1.4.0 and the free scan at https://gold.safeguard.sh/scan are good ways to test a single module first.

Quick check

Should vendor directories be excluded from scans?

Not blindly. Use them to confirm versions, because they may be what actually builds. Just avoid counting the same package twice.

How do I know whether a vendored package was edited?

Download the same version fresh and compare the files. Any difference means the copy was changed locally.

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.