govulncheck默认不扫描间接依赖,需加-test参数才能覆盖测试路径中引入的transitive依赖;正确做法是分别执行govulncheck ./和govulncheck -test ./,并配合go list -m all、go mod graph、go mod verify及osv-scanner进行全量依赖审计与校验。

govulncheck 必须加 -test 才能扫到间接依赖
默认 govulncheck ./ 只分析主模块显式 require 的包,大量真实漏洞藏在 golang.org/x/net、github.com/gorilla/mux 这类被二级依赖拉进来的模块里。不加 -test,等于只查了半张网。
正确做法是跑两遍:
-
govulncheck ./—— 覆盖业务代码路径 -
govulncheck -test ./—— 触发测试文件中加载的 transitive 依赖,常暴露日志、mock、http client 等链路里的隐藏风险
注意:GO-XXXX-XXX 是 Go 官方漏洞编号,不是 CVE;别拿它去搜 NVD,直接点报告里的链接跳转 vuln.go.dev 查原始上下文和修复建议。
go list -m all 是人工盯包的底线操作
govulncheck 不扫描 test-only 依赖,而很多高危包(比如 golang.org/x/crypto、github.com/kr/text)只在测试里用,线上不走,但 CI 构建时仍会下载并参与校验。这类包不会出现在 govulncheck 报告里,却可能被污染或含已知漏洞。
执行这行命令快速筛出高频风险模块:
go list -m all | grep -E "(golang\.org/x|github\.com/.*\.(sql|http|crypto|xml|yaml))"
对每个结果,再做两件事:
- 查它的
go.mod是否标了// indirect - 用
go mod graph | grep 包名看谁引入了它,判断是否可移除
go mod verify 不是可选,是 CI 第一行必须卡死的门禁
go.sum 只保证“和上次构建一致”,不保证第一次引入的就是干净的。你本地 go mod download 成功,不代表没下到被中间人篡改过的模块——尤其用了 GOPROXY=fallback 或私有 proxy 时。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
CI 流水线第一行就得跑:
go mod verify
失败必须中断。同时强制启用远程校验:
- 设环境变量
GOSUMDB=sum.golang.org(别信默认值,旧版 Go 默认关了) -
go.sum必须提交 Git,每次go mod tidy后要人工确认新增条目来源,比如突然多出github.com/xxx/yyy@v0.0.1,得查是不是团队内部库
osv-scanner 是 govulncheck 的关键互补工具
govulncheck 基于调用图分析,漏报常见;osv-scanner 直接比对 go.mod 里的所有模块版本与 OSV.dev 公共数据库,不依赖代码路径,能补上那些“没被调用但确实存在漏洞”的包。
一条命令就能扫全量依赖:
osv-scanner --skip-git-checks -r .
它还能输出离线可用的漏洞数据,适合隔离网环境;对每个漏洞,会按依赖深度和修复成本给升级建议,比纯列表更实用。
真正容易被忽略的是:漏洞是否被实际使用,和模块是否该被引入,是两个问题。前者靠 govulncheck 判断,后者靠 go list -m all + go mod graph + 人工决策。安全审计不是扫完就完事,而是持续清理“不需要却存在”的依赖。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










