Safeguard
Security Guides•

Why does govulncheck report fewer issues than my dependency scanner?

govulncheck reports only vulnerabilities whose functions your Go code can reach, while version matching lists every affected module. How to compare.

Safeguard Security Team
3 min read

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?

ApproachQuestionTypical result
Version matchingIs 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

  1. Export the version matching findings: module, version, advisory ID.
  2. Run govulncheck ./... on the same commit.
  3. 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.
  4. For advisories present in both, fix first. Those are reachable and known.
  5. 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.
  6. 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.

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.