大规模检测代码复制的利器:Vendetect

Vendetect是一款开源工具,通过语义指纹识别和版本控制感知技术,有效检测代码库间的复制和引用行为,帮助发现安全漏洞、跟踪许可证合规性,并支持多种检测算法扩展。

大规模检测代码复制:Vendetect工具解析

本月早些时候,Cheating-Daddy的维护者发现一家Y Combinator资助的初创公司复制了他们的GPL许可代码库,删除了注释,并以不兼容的许可证重新发布为"Glass"。这并非孤立事件;我们在安全评估中经常看到代码盗窃和不恰当的代码引用行为。因此,我们构建了一个自动检测工具。

Vendetect是我们新的开源工具,用于检测代码库之间的复制和引用代码。它使用语义指纹识别技术,即使变量名更改或注释消失,也能识别相似代码。更重要的是,与学术抄袭检测器不同,它理解版本控制历史,帮助您将引用代码追溯至其确切的源提交。

无人谈论的代码引用问题

在我们的安全评估中,我们经常遇到包含来自其他项目的复制粘贴代码块的代码库。有时这是合法的代码引用,但通常并非如此。问题比许可证违规更深入:

  • 安全债务悄然积累:当开发者从OpenSSL引用函数或从OpenZeppelin复制智能合约工具时,他们会继承该代码中的任何潜在漏洞。但如果不跟踪源版本,当CVE发布时,您无法知道自己是否受到影响。
  • 归属信息消失:我们看到过包含整个开源库但删除了版权声明的专有代码库。无论恶意还是意外,这都会产生法律责任。
  • 更新从未发生:引用的代码在时间中冻结。原始项目修复错误并添加功能,但复制的版本会逐渐腐化。

Vendetect的工作原理

Vendetect实现了Winnowing算法,与斯坦福大学MOSS抄袭检测器使用的方法相同,在计算机科学教授中很受欢迎。但我们已将其适应实际软件工程需求。

该算法通过创建代码的语义指纹工作,即使发生表面级别更改,这些指纹也能保持稳定。简化过程如下:

  1. 使用语言感知词法分析器(通过Pygments)对代码进行标记化
  2. 从标记流生成k-gram
  3. 对k-gram进行哈希处理,并使用滑动窗口选择子集
  4. 比较文件间的指纹以找到匹配项

这种方法即使当有人:

  • 重命名所有变量和函数
  • 删除注释和文档
  • 重新格式化或重构代码
  • 将制表符改为空格(是的,确实如此)

也能捕获复制的代码。

我们构建了Vendetect的模块化架构;Winnowing实现只是一个检测后端。该工具可以轻松集成其他方法,如JPlag的基于标记的匹配或基于AST的相似性检测。我们使用Python copydetect包进行核心Winnowing实现,这为我们提供了速度和可靠性。

版本控制感知改变一切

这就是Vendetect与学术抄袭检测器的不同之处:它理解git历史。

假设您正在审计代码库并发现可疑的加密实现。Vendetect不仅告诉您它与某些OpenSSL代码匹配,还能识别出它被复制的确切提交。现在您可以检查该版本是否具有Heartbleed漏洞,或自那时以来修复的数十个内存损坏错误。

此功能在评估中证明非常宝贵。我们发现:

  • 包含来自具有已知错误版本的OpenZeppelin代码的智能合约
  • 从包含弱点的预披露提交复制的加密库
  • 从带有硬编码后门的教程中提取的身份验证代码

该工具自动克隆和分析存储库历史,将您的目标代码库与多个版本进行比较,以找到最可能的源提交。

实际检测案例

在笔记本电脑上对Cheating-Daddy/Glass案例运行Vendetect大约需要10秒:

1
vendetect https://github.com/pickle-com/glass https://github.com/example/cheating-daddy

结果清楚地显示了跨多个文件的大量复制,具有高相似性分数,尽管Glass试图通过删除注释和重新格式化来隐藏来源。

在智能合约评估中,引用检测更为关键。以太坊开发者经常从成熟项目中复制实用函数、数学库和安全模式。虽然通常合法,但这种做法会创建隐藏的依赖关系。

实际使用Vendetect

安装很简单:

1
pip install vendetect

基本用法比较两个存储库:

1
2
3
4
5
6
# 本地存储库
vendetect /path/to/suspect/repo /path/to/source/repo
# 远程存储库
vendetect ./my-project https://github.com/openssl/openssl
# 自动化输出格式
vendetect repo1 repo2 --format json > results.json

默认的丰富输出显示并排代码比较与相似性百分比。JSON输出可轻松集成到CI/CD管道中,用于自动许可证合规性或安全检查。

超越抄袭检测

我们构建Vendetect是为了解决我们在安全评估中遇到的实际问题,但其应用超出了捕获代码窃贼的范围:

  • 供应链安全:识别代码库中的所有引用依赖项,特别是传统依赖管理器未跟踪的依赖项。
  • 许可证合规性:自动验证引用代码是否保持适当的归属和兼容许可。
  • 安全补丁跟踪:当宣布CVE时,通过与修补版本比较,快速检查您的引用代码是否受到影响。
  • 代码考古学:当文档缺失或不正确时,追踪遗留代码的谱系。

扩展Vendetect

Vendetect的模块化架构使得实验不同的检测算法变得容易。如果您实现了自己的相似性检测方法,无论是基于AST分析、机器学习嵌入还是新颖算法,我们都希望听到您的消息。该工具提供了一个清晰的接口用于添加新的检测后端:

1
2
3
4
5
6
7
8
class MyComparator(vendetect.comparison.Comparator[MyFingerprint]):
    def fingerprint(self, path: Path) -> MyFingerprint:
        # TODO: 对`path`处的文件进行指纹处理
        return my_fingerprint

    def compare(self, fp1: MyFingerprint, fp2: MyFingerprint) -> Comparison:
        # TODO: 比较两个指纹并返回结果
        return comparison

我们特别感兴趣的是可以改进特定领域检测的方法,例如智能合约或嵌入式系统,在这些领域中传统的基于文本的匹配会失败。

亲自尝试

下次您怀疑代码被复制时,无论您是在调查许可证合规性、追踪漏洞来源,还是只是对代码来源感到好奇,请尝试Vendetect。

该工具可在GitHub和PyPI上获得。如果您实现了新的检测后端或找到了有趣的用例,请联系我们。我们始终致力于根据实际需求改进我们的工具。

代码引用不会消失。但通过适当的工具,我们至少可以使其可见、可跟踪和可管理。因为当您甚至不知道安全债务存在时,它积累得最快。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计