快速识别Go项目中GPL/AGPL包需用go-licenses工具扫描依赖树并导出许可证文件:安装go install github.com/google/go-licenses@latest,执行go-licenses save . --save_path=third_party_licenses生成报告,检查输出中是否含GPL-3.0、AGPL-3.0等关键词;不可依赖go list -m -json all因许多包未声明License字段。

怎么快速识别项目里用了 GPL 或 AGPL 包
Go 项目里混入 GPL 类许可证(尤其是 GPLv3、AGPLv3)会直接威胁二进制分发合规性,但 go mod 默认不暴露许可证信息。必须用专用工具扫描依赖树并提取每个模块的 LICENSE 文件或声明。
最可靠的方式是用 go-licenses 导出全量许可证报告:
- 先安装:
go install github.com/google/go-licenses@latest - 执行:
go-licenses save . --save_path=third_party_licenses,它会把每个依赖的 LICENSE 文件复制到指定目录,并生成THIRD_PARTY_NOTICES.md - 检查输出文件里是否含
GPL-3.0、AGPL-3.0、SSPL等关键词——注意大小写和空格变体(如gpl-3.0也算)
别只信 go list -m -json all | jq '.License',很多包没在 go.mod 里声明 License 字段,JSON 输出为空不代表安全。
replace 能绕过 GPL 吗?什么情况下合法
replace 只改变代码来源路径,不改变许可证约束。如果原包是 GPL,你用 replace github.com/xxx/lib => ./fork 指向自己改写的 MIT 版本,前提是:你确实重写了全部 GPL 代码、移除了所有原始作者版权声明、且新版本已明确声明为 MIT —— 否则只是掩耳盗铃。
立即学习“go语言免费学习笔记(深入)”;
真正可行的替换路径只有两种:
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 找到功能等价的 MIT/Apache-2.0 替代品(例如用
github.com/gofrs/uuid替换github.com/satori/go.uuid) - 自己实现核心逻辑(比如只用标准库
crypto/rand+encoding/hex生成 UUID),彻底摆脱第三方依赖
常见陷阱:replace 到一个 fork 仓库,但那个 fork 仍保留 GPL 声明,甚至没改 LICENSE 文件——这种替换毫无法律效力。
如何验证替换后的包真被用了
写了 replace 不等于生效。Go 工具链只在满足三个硬条件时才触发替换:
-
go.mod中的replace左侧路径(如github.com/xxx/lib)必须和代码里import的路径、以及require行中的路径**完全一致**(包括大小写、末尾斜杠) - 右侧本地路径(如
./local-lib)下必须存在go.mod,且其中module行声明的路径与左侧完全匹配 - 执行过
go mod tidy或至少一次go build,否则缓存未刷新,go list -m all仍显示旧路径
验证是否生效的唯一方法是运行:go list -m -f '{{.Replace}}' github.com/xxx/lib,输出应为 ./local-lib;若为空字符串,说明替换失败,仍在拉远程。
CI 流程里必须卡住许可证风险
人工扫描不可靠,必须在 CI 中自动拦截。建议在构建第一步加校验脚本:
- 跑
go-licenses report . --format=json > licenses.json - 用
jq提取所有非白名单许可证:jq -r 'select(.License | contains("GPL") or contains("AGPL") or contains("SSPL")) | .Package' licenses.json - 若输出非空,直接
exit 1
白名单建议只包含 MIT、Apache-2.0、BSD-3-Clause;BSD-2-Clause 和 ISC 需法务确认;Unlicense 和 CC0-1.0 在 Go 生态极少出现,但理论上可接受。
注意:go-licenses 无法检测动态加载的 C 库(如 cgo 绑定的 OpenSSL),这类风险需单独审计。

















