Check your go.mod for vulnerable Go modules
toolchain line is checked for end of life.Checked against OSV.dev, CISA KEV, FIRST EPSS, npm, PyPI, deps.dev, endoflife.date and Docker Hub, live.
Sample: A Gin API’s go.mod
A Gin API with advisories in its direct modules, an archived JWT library with no fix, two indirect modules and a toolchain line on a Go release that is past end of life.
module github.com/acme/api go 1.21 toolchain go1.21.5 require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gin-gonic/gin v1.7.0 github.com/golang-jwt/jwt/v4 v4.4.1 golang.org/x/crypto v0.14.0 golang.org/x/net v0.7.0 ) require ( golang.org/x/text v0.3.7 // indirect google.golang.org/protobuf v1.28.0 // indirect )
8 findings: 6 critical and 2 warnings
7 packages from go.mod
Critical: 22 known vulnerabilities in golang.org/x/net 0.7.0
go.mod0.60.0CVE-2023-44487 exploited in the wild (CISA)
Critical: 23 known vulnerabilities in golang.org/x/crypto 0.14.0
go.mod0.56.0
Critical: CVE-2020-26160 in github.com/dgrijalva/jwt-go 3.2.0
go.mod
Critical: 3 known vulnerabilities in github.com/gin-gonic/gin 1.7.0
go.mod1.9.1
Critical: 2 known vulnerabilities in github.com/golang-jwt/jwt/v4 4.4.1
go.mod4.5.2
Critical: Go 1.21 is end-of-life
go.mod toolchain1.27.2
And 2 more findings in the full result.
Last checked against GitHub, OSV.dev, deps.dev, CISA KEV, FIRST EPSS and endoflife.date.
What it reads in go.mod
requirelines, single and in blocks, at the version written.+incompatibleversions are handled.// indirectmodules, tagged Indirect and ranked one level lower.- The
toolchainline, checked for end of life. Thegoline is a minimum, so it isn’t checked. - Module deprecation notices, which deps.dev reads from each module’s own go.mod.
Why go.mod versions are exact
Go builds use minimal version selection, and since Go 1.17 a module’s go.mod requires every module that provides a package it imports, directly or not. After go mod tidy, the versions in go.mod are the ones your build uses, so unlike npm or pip there are no ranges to guess from. That makes go.mod the whole answer for a module-level check.
How it compares with govulncheck
| Tool | What it reads and checks | Use it when |
|---|---|---|
| govulncheck | Your source code or a built binary, against the Go vulnerability database. Static analysis narrows reports to vulnerable functions your code can reach, and it covers the standard library of your Go version. | You can run it in the module or in CI and want only findings your code can reach. |
| This check | The go.mod you paste, with no code or Go install. Reports every required module with an advisory, reachable or not, ranks by CISA KEV and EPSS, flags deprecated modules and checks the Go toolchain for end of life. | A quick look at a repo you haven’t cloned, reviewing a go.mod change, or handing your coding agent a ranked upgrade list. |
Your source code or a built binary, against the Go vulnerability database. Static analysis narrows reports to vulnerable functions your code can reach, and it covers the standard library of your Go version.
Use it when: You can run it in the module or in CI and want only findings your code can reach.
This check
The go.mod you paste, with no code or Go install. Reports every required module with an advisory, reachable or not, ranks by CISA KEV and EPSS, flags deprecated modules and checks the Go toolchain for end of life.
Use it when: A quick look at a repo you haven’t cloned, reviewing a go.mod change, or handing your coding agent a ranked upgrade list.
Because this check doesn’t look at call paths, it can report a module whose vulnerable function you never call. govulncheck can rule those out, so run both if you can.
Questions
Does it check the Go standard library?
Not advisory by advisory. Standard library fixes ship in Go releases, so the check looks at your toolchain line and says whether that Go release is still supported. govulncheck reports standard library advisories for the Go version you build with.
Why is an indirect module only a warning?
A // indirect module is there because something you depend on needs it, and you usually fix it by upgrading that dependency or adding a direct requirement at the fixed version. Its critical advisories rank as warnings, unless CISA lists them as exploited.
A module has no fixed version. What now?
Usually the module is abandoned. The sample’s github.com/dgrijalva/jwt-go is an archived repository whose advisory has no fix; its maintained successor is github.com/golang-jwt/jwt. Replace the import, then run go mod tidy.
Are replace directives applied?
No. A module you replaced with a fork or a local path is checked at the version you required, so a finding on it may not apply to your fork.
Do I need go.sum?
No. go.sum holds checksums, not versions; go.mod already names the version of every module your build uses.
Go further than one check
Map your repo into an architecture diagram with live health on every part, get an alert when a new critical finding lands, and hand your coding agent a brief to build from. Free to start.