必须配置 GOPRIVATE 防止私有模块经公共代理拉取,并在 CI 中强制校验 go.sum、禁用自动修改、结合 replace 与 go mod verify 拦截非白名单依赖,缺一不可。

用 GOPRIVATE 禁止走公共代理拉取私有/敏感模块
Go 默认会通过 proxy.golang.org 下载所有未明确标记为“私有”的模块,哪怕你写的是 git.company.com/internal/logging,只要没配置 GOPRIVATE,它仍会先尝试走代理——失败后才 fallback 到 direct,但这个过程可能被中间人劫持或缓存污染。
必须在团队所有开发机和 CI 环境中统一设置:
-
GOPRIVATE=git.company.com/*,github.com/myorg/*(支持通配符,多个用逗号分隔) - 推荐写入 shell profile 或 CI 的 env 配置块,避免仅靠本地
go env -w——后者不继承到子进程,CI 构建常失效 - 验证是否生效:
go env GOPRIVATE必须输出非空;再执行go list -m github.com/myorg/secretlib@latest,若没报proxy.golang.org相关错误,说明已绕过代理
在 CI 中强制校验 go.sum 且拒绝新增未签名依赖
go.sum 是 Go 依赖完整性校验的唯一依据,但它默认不阻止新增条目。团队一旦有人运行 go get,go.sum 就自动追加新 checksum,无人审核就进了主干。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- CI 流程第一步加检查:
git diff origin/main -- go.sum | grep '^+' | grep -q '^[+][^+]' && echo "ERROR: go.sum changed" && exit 1 || true—— 拒绝任何go.sum新增行 - 真正需要更新时,由安全小组手动运行
go mod download -json+ 人工核对来源、版本、checksum,再提交 - 禁用
go mod tidy在 CI 中自动修改go.sum:用GOFLAGS="-mod=readonly"启动所有go命令,这样go build失败时会明确提示 “go.sum is out of sync”,而不是静默修正
用 replace + go mod verify 拦截非白名单依赖
Go 不提供原生依赖白名单机制,但可用 replace 反向控制:把所有非白名单模块强制替换为一个空包或 panic 包,让构建当场失败。
例如,在 go.mod 底部加:
replace github.com/badactor/malware => ./internal/forbidden replace golang.org/x/exp => ./internal/forbidden
然后确保 ./internal/forbidden/go.mod 存在且内容为:
module internal/forbidden go 1.21
再配合 CI 中运行 go mod verify —— 它会检查所有 require 条目是否在 go.sum 中有对应 checksum,而被 replace 的模块不会触发下载,因此只要 go.sum 里没它们的记录,go mod verify 就直接失败。
为什么不用 go vet 或静态扫描工具拦依赖?
因为 go vet 只检查代码语法和常见模式,不解析 go.mod;第三方扫描工具(如 gosec、govulncheck)只能查已下载的依赖,无法阻止 go get 行为本身。
真正卡点必须落在两个位置:
- 下载阶段:靠
GOPRIVATE和代理策略切断非授权源 - 构建阶段:靠
GOFLAGS="-mod=readonly"+go mod verify+replace组合,让任何未经审批的require条目无法通过 CI
漏掉任意一环,go get github.com/xxx@v0.0.0-20230101000000-xxxxxxxxxxxx 这种伪版本就能绕过所有审查。


















