测试依赖项的充分理由:AGPL版本

在这里,您获得了BSD,MIT和Apache2许可下的代码,不要犹豫,然后-bam! -第二个转变,在传递依赖中,绘制了AGPL下的代码。 我们试图留意这一点,并宁愿超车而不是未完成。



在向我的任何项目添加新的依赖项之前,我总是进行基本检查。 我要检查的内容(标准清单):

  • 该代码以什么许可证颁发?
  • 谁是作者?
  • 错误跟踪器中是否存在严重的未解决问题?
  • 错误跟踪器中是否有严重错误的历史记录?
  • 拉取代码的代码审查如何发生?

之后,我会浏览代码本身,以寻找明显不安全或恶意的内容。 这对于感觉代码库本身的质量很有必要。 接下来,我尝试找到“棕色的M&M” -细微的细节可能表明存在重大问题。 并递归地重复上述所有带有传递依赖项的操作。 此外,每次更新依赖项时,我都会再次浏览代码。

这是一项相当大的工作,但是为了不成为事件流之类的攻击的受害者,这是必要的。 最近,我想起了检查依赖项的另一个很好的理由。 那时,我正在对Duo上为WebAuthn on Go 积极宣传的库进行审查,它位于这里: github.com/duo-labs/webauthn

这一切都始于我注意到一些“棕色M&M”的事实:

  • 尽管这是一个库,但数据已在stdout中记录。
  • 该代码已存储。

当然,这些小问题只是预示着更多的事情:当我开始回顾其中一个传递性依赖项( github.com/katzenpost/core/crypto/eddsa )时, AGPLv3许可证标头让我很满意

对于任何想使用Duo的WebAuthn库的人来说,这都是一个坏消息。 尽管Duo在BSD下许可了它的库,但选择了它,您仍然将应用程序与AGPL库链接。 而且,根据(A)GPL,您可以按照AGPL第13条的规定创建“修改的”产品:
如果您对该程序进行更改,则修改后的版本应明确为所有通过网络与该程序进行远程交互的用户(如果您的版本支持此交互)提供了使用标准软件复制工具免费免费访问该版本的源代码的机会(尽管遵守本许可的任何其他规定)。
换句话说,如果您在公共Web应用程序中使用了github.com/duo-labs/webauthn ,则您的Web应用程序现在应该是开源的。

关于这种依赖关系,最离谱的是它复制了golang.org/x/crypto/ed25519-Go 标准 “ x”库之一

实际上, github.com/duo-labs/webauthn与最初使用的golang.org/x/crypto/ed25519相同。 替代是在一项名为“将COSE事物整合到自己的领域”的外部协作的拉动请求中进行的。 在将部分代码从一个文件传输到另一个文件的过程中,此拉取请求悄悄更改了OKPPublicKeyData.Verify的实现。

这是使用OKPPublicKeyData.Verify

 // Verify Octet Key Pair (OKP) Public Key Signature func (k *OKPPublicKeyData) Verify(data []byte, sig []byte) (bool, error) { f := HasherFromCOSEAlg(COSEAlgorithmIdentifier(k.PublicKeyData.Algorithm)) h := f() h.Write(data) return ed25519.Verify(k.XCoord, h.Sum(nil), sig), nil } 

这是OKPPublicKeyData.Verify ,它使用了AGPL许可的github.com/katzenpost/core/crypto/eddsa

 // Verify Octet Key Pair (OKP) Public Key Signature func (k *OKPPublicKeyData) Verify(data []byte, sig []byte) (bool, error) { f := HasherFromCOSEAlg(COSEAlgorithmIdentifier(k.PublicKeyData.Algorithm)) h := f() h.Write(data) var oKey eddsa.PublicKey err := oKey.FromBytes(k.XCoord) if err != nil { return false, err } return oKey.Verify(h.Sum(nil), sig), nil } 

没有对此变化进行解释。 pullrequest审查由两名 Duo 员工进行 ,得到批准,并保留下来。

这就是为什么我不喜欢接受移动代码的请求的原因。 即使新的代码组织比上一个更好,但检查“执行新的pull-quest是否做了多余的事情”所花费的时间也浪费了太多时间。

发布了有关带有AGPL许可证的库依赖性的警告 ,开发人员返回了 golang.org/x/crypto/ed25519 。 尽管如此,我还是决定不使用github.com/duo-labs/webauthn 。 该库的大部分内容及其依赖项旨在支持称为证明的WebAuthn错误功能,而我的使用意愿不到零。 我刚刚完成了一个更简单,无需证明的库的编写,它比上面的十分之一小。 很快我将打开其源代码。 该库的开发成本比使用现有WebAuthn Go库的责任便宜。

这个案例使我想起了为什么我喜欢在Go上编程。 借助Go广泛的标准和准标准“ x”库,我的项目中通常很少有其他依赖项。 Go的良好声誉和操作程序使我不必费力气,也不必再次检查编译器和标准库的源代码。 而且,尽管事实上我喜欢Rust,但每次查看它们典型库的依赖树时,我都会感到恐惧:通常,我看到数十个由互联网上晦涩的随机家伙编写的传递性依赖,我没有理由信任它们。 检查所有这些依赖项会花费太多时间,因此我在Rust中的工作效率比Go差很多。

最后一点:作为证书透明度等可验证数据结构的支持者,我必须喜欢新的Go校验和数据库 。 但是,如果您不花时间检查依赖项,那么校验和数据库将无济于事。 不幸的是,我已经看到一个过分热情的Go用户声称校验和数据库解决了依赖管理的所有问题。 但是事实并非如此。 没有简单的方法可以摆脱这种情况,并且您需要接受一个事实:您有时需要在项目中进行依赖项审查。

Source: https://habr.com/ru/post/zh-CN484898/


All Articles