目录
- 1. 引入
- 2. 现有漏洞识别方案的不足
- 2.1 数据集中label不准
- 2.2 数据重复
- 2.3 测评标准不够好
- 3. 现有漏洞识别数据集分析
- 3.1 关于现有数据集中label的准确率分析
- 3.2 关于现有数据集中数据泄露( Data Leakage)情况分析
- 4. 漏洞识别测评
- 5. PrimeVul数据集构建过程
- 5.1 数据合并
- 5.2 数据去重
- 5.3 数据打标
- 5.4 数据切分
- 6. 模型测评情况
- 6.1 对开源代码大模型进行微调后的测评
- 6.2 对GPT4和GPT3.5进行测评
- 7. 总结
- 8. 参考
1. 引入
参考1是2024年5月份发表在ICSE(47th IEEE/ACM International Conference on Software Engineering (ICSE 2025))上的一篇文章,文章题目是"Vulnerability Detection with Code Language Models: How Far Are We?"。它对现阶段的漏洞数据集进行了分析,指出了现有数据集label不准和数据重复的问题,现有根据ACC/F1来做漏洞识别模型评测的不足,并给出了作者构建的另一个高质量数据集PrimeVul,还用这个数据测评了现有的SOTA的一些模型,并得出了现有模型做漏洞识别能力都不足的结论。
下面详细解读其核心思想。
2. 现有漏洞识别方案的不足
2.1 数据集中label不准
- 大部分数据集,都是自动打标,比如根据漏洞修复的commit来对函数打标。但真实世界中,修复漏洞的同时,也会对其他代码做调整,这样打标就导致误标。
2.2 数据重复
- 数据重复:发现18.9%的样本在测试集和训练集中同时存在
2.3 测评标准不够好
- 漏洞检测任务不适合用accuracy来做评价,因为真实世界中漏洞很少,一直输出0就能得到很高的acc
- 真实世界中漏洞检测,防止误报很重要
3. 现有漏洞识别数据集分析
3.1 关于现有数据集中label的准确率分析
现有数据集分析:
(1)Juliet和SARD这种老数据集不能表示真实世界漏洞的复杂性;
(2)真实开源软件的漏洞:自动label的不准,手动label成本高。
手动label,成本高。比如SVEN数据集,虽然量少(1606个函数,半数都有洞),但质量高。
自动label的方法,一般是这样做的:收集漏洞修复commit,把修复前的作为有洞数据,修复后的作为无洞数据。随机取样分析,每个数据集随机抽样50个函数,3个人工检查,最终按投票决策,发现现有数据集label本身准确率较低,见表1。
BigVul,CrossVul,CVEFixes,DiverseVul这四个都是比较知名的数据集,从表格中的数据看,准确率也都不行。
3.2 关于现有数据集中数据泄露( Data Leakage)情况分析
文中的 Data Leakage,指的是:测试集中含有训练集中的数据。作者认为,目前大部分已经存在的漏洞数据集中,造成数据泄露的两种情况是(1)数据复制(2)时间顺序错乱。
(1)数据复制
作者按照现有数据集来分析其训练集和测试集中函数的重复性,得到的结果如下图:
对于DiverseVul,它虽然做过hash去重,但还是有3.3%的重复率,因为它没有对格式化字符做归一化(比如空格的数量不同)。
(2)时间顺序错乱
大部分数据集构建时,采用随机切分数据集为训练集、测试集,这带来的问题:
随机划分函数到不同集合中,会导致训练和测试数据在时间顺序上不合理,出现数据时间顺序错乱的 “时间穿越” 现象,这种现象会使得模型训练和测试的结果不能真实反映模型在实际应用(用过去数据训练预测未来数据)中的性能 。
4. 漏洞识别测评
真实世界中的漏洞检测,开发者不关注F1和ACC,而是关注
(1)减少漏洞和误报;
(2)对于文本上相似的代码样本(包括有漏洞的样本和已修复补丁的样本)的区分能力,也就是模型能否准确地区分有漏洞的代码和已经修复了漏洞的代码,即使它们在文本内容上很相似。
漏报太多,会导致安全问题;误报太多,看不过来。所以漏报和误报要平衡折中。作者认为:
(1)漏报率FNR要越低越好;
(2)有一些误报FPR是可以接受的
作者提出的测评标准是Vulnerability Detection Score (VD-S)。公式为:FNR@(FPR≤r) ,其中 r∈[0%, 100%] 是可配置参数,文中选择 r = 0.5% 进行评估。如果一个漏洞检测模型的 VD-S 为 10%,意味着在误报率被控制在 0.5% 的情况下,仍有 10% 的真实漏洞可能被漏检。所以VD-S越低越好。
5. PrimeVul数据集构建过程
高质量数据集PrimeVul的构建过程:
5.1 数据合并
首先,对真实世界的数据集进行合并。作者将BigVul、CrossVul、CVEfixes和DiverseVul这些数据集中函数进行合并。作者没有使用Devign和CodeXGLUE数据,因为作者发现这两数据集中的内容的很大一部分与安全问题无关。
5.2 数据去重
去除空格、制表符(“\t”)、换行符(“\n”)和回车符(“\r”)等字符,对提交前后已更改的函数进行规范化处理。然后,我们计算已更改函数在提交前版本和提交后版本的 MD5 哈希值。如果一个函数的提交前版本和提交后版本产生相同的哈希值,我们就认为这个函数没有发生变化,并且将其舍弃。
5.3 数据打标
作者构建了两种数据打标策略,进一步提高label的正确率:
(1)PRIMEVUL-ONEFUNC
标注规则:如果某个函数是与安全相关的提交中唯一被更改的函数,那么就将这个函数视为存在漏洞的函数。
也就是说,在之前的标注方法中,当一个提交commit修改了多个函数时,可能会在判断哪个函数真正存在漏洞。而 PRIMEVUL-ONEFUNC 方法通过限定只有当某个函数是安全相关提交中唯一被改动的函数时才认定它有漏洞,避免了在多函数修改提交情况下标注的模糊性和错误,提供了一种更明确、更准确的标注方式来确定函数是否存在漏洞 ,从而提高了数据标注的质量,有助于后续漏洞检测模型的训练和评估。
(2)PRIMEVUL-NVDCHECK
**关联数据:**首先,我们将与安全相关的代码提交(commits)与其对应的 CVE 编号以及 NVD 数据库中的漏洞描述进行关联。
数据标注:
- NVD 的描述中明确指出了该函数存在漏洞。这意味着在 NVD 对某个 CVE 的详细描述中,直接提到了这个函数是有问题的,那么根据这个权威信息,我们就可以将该函数标记为存在漏洞。
- 当 NVD 的描述提到了某个函数所在的文件名,并且在这个文件中,这个函数是唯一因与安全相关的提交而被更改的函数时,该函数也会被认定为存在漏洞的函数。
5.4 数据切分
不是随机切分训练集、测试集。而是根据时间切分,老数据做训练集,新数据做测试集。
最终,得到的数据集PrimeVul如下:
6. 模型测评情况
作者对如下模型进行了测评
对CodeT5等开源代码大模型,用PrimeVul微调后做了测评。
6.1 对开源代码大模型进行微调后的测评
微调时,对StarCoder2和CodeGen2.5,epoch=4;对CodeT5和CodeBERT,epoch=10。微调后的模型测评结果如下:
虽然 StarCoder2 模型在 BigVul 基准测试上表现出了值得称赞的 F1 分数(达到 68.26%),但在 PrimeVul 基准测试上,它的 F1 分数却急剧下降到了微不足道的 3.09%。这种大幅下降并非个例,而是在所有模型中都能观察到的一种趋势,这从观察到的漏报率中就可以得到例证。也就是说,之前基于 BigVul 等基准测试所认为的模型具有较好的漏洞检测能力,其实是不准确的,当使用更能反映现实漏洞复杂性的 PrimeVul 基准测试时,这些模型的真实表现很差,漏报率较高,无法有效地检测出漏洞。这表明之前的基准测试存在局限性,不能真实反映代码语言模型在实际漏洞检测任务中的性能。
作者还做了更复杂的训练,结果表明,用于二分类的先进训练技术,例如对比学习和类别权重,并不能显著提升代码语言模型在 PrimeVul 数据集上的性能,这突显了该任务在现实中的难度。
6.2 对GPT4和GPT3.5进行测评
我们对 GPT-3.5 进行微调时,我们注意到该模型受到了漏洞样本与良性样本 1:3 比例的强烈影响,其表现甚至比使用提示方法时还要差。这是一个危险信号,表明即使是这样一个大型的语言模型(LLM),仍然无法捕捉到漏洞模式,而是选择了从数据中走捷径(即依赖数据中的表面特征而非真正理解漏洞模式)。
所以,作者认为,即使是最先进的 OpenAI 模型,在 PrimeVul 数据集上也无法取得可靠的性能表现,这就需要从根本上采用全新的方法来改进这项任务。
7. 总结
PrimeVul作者对现有漏洞数据集进行分析,指出了现有数据集label不准和数据重复的问题,现有根据ACC/F1来做漏洞识别模型评测的不足,并给出了作者构建的另一个高质量数据集PrimeVul,还用这个数据测评了现有的SOTA的一些模型,并得出了现有模型做漏洞识别能力都不足的结论。作者的分析方法和高质量数据集构建的思路非常值得借鉴。
8. 参考
- https://arxiv.org/abs/2403.18624