govulncheck reports a vulnerability only when your code transitively calls the vulnerable function, according to the Go team. A scanner that matches module versions against advisories lists every affected module in the graph. Neither is wrong. They answer different questions, and the gap is your triage queue.
What each approach reports
The Go vulnerability documentation says govulncheck analyzes your code and surfaces only vulnerabilities that affect you, by checking whether functions in your code transitively call vulnerable functions. It reads the Go vulnerability database, whose reports are in OSV format and reviewed by the Go Security team.
A version matching scanner asks a simpler question: is a module at an affected version present in go.mod or go.sum?
| Approach | Question | Typical result |
|---|---|---|
| Version matching | Is an affected module version present? | Longer list, includes unused code |
| Reachability (govulncheck) | Can my code call the affected function? | Shorter list, higher signal |
The Go supply chain article supports the premise: modules that do not contribute code to a specific build have no security impact on it.
Myths and facts
Myth: A shorter list means the scanner missed things. Fact: The shorter list removes findings in code your program never calls. Confirm by looking at the call path in the output.
Myth: Unreachable means ignore forever. Fact: Reachability can change when you add a feature or import a new package. Rerun on every change.
Myth: Reachable means exploitable. Fact: It means your code calls the function. Exploitability still depends on inputs, configuration and exposure.
How to reconcile two reports
- Export the version matching findings: module, version, advisory ID.
- Run
govulncheck ./...on the same commit. - For each advisory in the first list but not the second, check the module with
go mod why -m. If your build does not import it, the difference is explained. - For advisories present in both, fix first. Those are reachable and known.
- For advisories only in the longer list, schedule an upgrade anyway if it is cheap. Unreachable findings still count in compliance evidence and in the next refactor.
- Keep notes on why an item was deprioritised, so the decision survives staff changes.
Also remember coverage depends on the database. Review the database entry rather than assuming it is complete, and see govulncheck database coverage and delay.
Try it yourself
Click through it at your own pace, or open it full screen. Compare the count before and after reachability is applied.
Where Safeguard fits
Safeguard combines SBOM and dependency scanning with reachability analysis, so you can see both the full inventory and the reachable subset. Try a free scan.
Quick check
Does govulncheck use a call graph?
Yes. The Go documentation describes it as checking whether your functions transitively call vulnerable functions.
Should I ignore unreachable findings?
Deprioritise them, but recheck after code changes and upgrade when it is cheap.
Sources
Last reviewed: 19 October 2026.