tea 是 Gitea 的 CLI 前端命令行程序,已被 Manjaro 、Arch Linux 等多个 Linux 发行版采用。但网友 Artemis Everfree 在打包 tea 程序的时候,意外发现该程序的多个依赖项都没有明确的开源许可。
举个例子,在使用 Golicense(一个扫描 Go 程序的依赖性及许可的工具)进行扫描后,扫描结果显示:
🚫 gitea.com/noerw/unidiff-comments <license not found or detected>
这是一个 Go 的文件差异解析器 ,Artemis 进一步检查了这个 gitea.com/noerw/unidiff-comments 依赖,发现这个 unidiff-comments 包实际上只是 GitHub 上 godiff 项目的镜像,针对 Go 模块进行了单独打包。
而更搞的是:原版 godiff 仓库就是没有许可证的,而且已经六年没有更新了。unidiff-comments 的作者 noerw 也意识到自己 Fork 了一个无许可的项目,早在 2020 年就在原始仓库提过 Issue 让作者加一个开源许可证,但一直没有得到回应。
不过,在 Artemis Everfree 关于此事的博客引起热议之后,有网友联系到了原作者,原作者惊奇地评论道:“这是 7 年前的项目啊,当初实在是没想到有人会用我的代码,所以就没管许可证的事情。不过如果它能提供帮助,那我就添加一个 MIT 许可证好了。”
关于这个依赖项的问题暂时得到了解决,但这也反映了一些问题: Linux 发行版只关注软件包自身的许可证,但对该软件包的依赖树缺乏审查。要知道,GNU 自由系统发行指南上明确规定:
- 发行版的信息和源文件必须按照合适的自由许可证提供。
- 发行版不应该带有非自由软件的资源库,或安装非自由软件的指导。
- 发行版也不应该指向未承诺只包含自由软件的第三方资源库。
- 发行版的开发者尽力避免非自由软件,并承诺一旦发现有非自由程序就移除。
而此次众多的 Linux 发行版中存在着不满足许可条款的 go 软件包,里面包含大量无许可的代码,这显然不符合发行指南的要求。
当然问题肯定不止于 Go 包,只是静态编译依赖项的生态进一步加剧了 Linux 分发基础设施的脆弱性。
静态链接意味着将程序的依赖项直接嵌入到程序中,它与动态链接(或动态加载)相反,动态链接将依赖库保存在单独的文件中,这些文件在程序启动(或运行时)时加载。
静态链接会使依赖项成为程序的一个组成部分,不能轻易地被另一个版本取代。如果其中一个库易受攻击,则必须将整个程序重新链接到新版本。
长期以来,Linux 发行版(Debian / Fedora /Gentoo 等)都在反对静态链接、固定依赖和依赖捆绑,但收效甚微,因为 Go 和 Rust 这些编程语言完全依赖于静态链接,而这些语言的生态仍在不断发展壮大。这导致发行版每纳入一个新的 GO/Rust 软件,就需要对它自身以及爆炸性的依赖树逐一盘查许可,这对审查工作是非常沉重的负担。
另外,该事件在 Reddit 帖子的热议也暴露另一个问题 —— 大多数开发者对开源许可证的重要性没有明确的认知,对不同许可证之间的差异也只是一知半解,开源许可的科普之路任重而道远。