用于软件漏洞检测的大型语言模型:研究人员关于模型、方法、技术、数据集和指标的指南
Large language models for software vulnerability detection: a guide for researchers on models, methods, techniques, datasets, and metrics
发布在International Journal of Information Security,2025 一月 29
摘要
大型语言模型(LLMs)在软件漏洞检测与管理领域中,已成为变革性的工具,展现出识别、分析和缓解安全风险的复杂能力。本文深入探讨了LLMs的应用,审视其在革新传统软件漏洞检测方法中的作用。我们探索了多种类别的LLMs,例如基于transformers的双向编码器表示(BERT)和生成式预训练transformer(GPT),以及这些模型如何被用于提高漏洞检测的准确性和效率。
本文回顾了LLMs如何被集成到现有的软件安全框架中,并综合了有关其在不同场景中表现的研究成果。文章提供了LLM方法如何补充静态分析和模糊测试等传统技术的见解,但并未对这些方法进行直接比较分析。通过对这些方法的对比,突显了LLMs的优势,如其能够跨多种代码库和编程语言进行泛化,同时也指出了其局限性,例如对训练数据偏见的敏感性和幻觉问题 。
本文综合了近期研究的发现,展示了LLMs在检测从缓冲区溢出到SQL注入等各种漏洞方面的成功应用,并概述了这些模型如何通过自动化检测和报告安全缺陷来提升生产力。此外,我们还讨论了将LLMs应用于软件漏洞检测所面临的固有挑战,例如对高质量数据集的需求,以及在安全性关键应用中部署基于LLM系统的伦理问题。解决这些挑战对于LLM技术在未来网络安全领域的进一步发展至关重要。
本文提供了基础和专业数据集的全面介绍,包括为软件漏洞检测量身定制的数据集,如CVEfixes、Big-Vul和LineVul。这些数据集是训练和基准测试LLMs的重要资源。
此外,我们介绍了用于评估模型在检测和缓解漏洞方面性能的评价指标,如F1分数、精确率、召回率和AUC-ROC,提供了一种结构化的方式来衡量LLMs的成功与局限。
此外,本文探讨了微调技术,如全微调、特征提取、基于适配器的微调和LoRA(低秩适应),强调了每种方法如何增强LLMs在漏洞检测中的性能。
通过关注参数高效的微调方法,如适配器层、前缀微调和LoRA,我们概述了优化模型性能同时减少计算开销的方法。通过提供对现有文献的全面回顾和对LLM集成的实际见解,本文旨在填补现有研究中的空白,并作为未来研究的基础指南。本文提供的比较分析、详细案例研究和战略性建议,将使软件安全领域的研究人员和从业者受益匪浅,共同突显LLMs在补充和增强传统软件漏洞检测技术方面的潜力。
关键词 安全与隐私 · 软件与应用安全 · 软件安全工程 · 计算方法 · 机器学习 · 机器学习方法 · 大型语言模型(LLMs) · 软件漏洞 · 软件漏洞检测 · 软件漏洞数据集 · 漏洞检测指标 · 微调技术
1 引言
软件应用程序中实现错误的存在可能表现为程序崩溃、数据损坏、性能下降以及可被利用的安全漏洞。这凸显了早期识别和修复错误的重要性。尽管静态分析等传统方法在检测错误方面具有一定的价值,但其准确检测故障的能力有限。而基于深度学习(DL)的最新尝试可能无法全面捕捉软件代码的复杂性。虽然静态分析和DL技术在错误检测的初始阶段提供了显著的价值,但它们容易生成误报和其他挑战(数据需求、可解释性、特征选择)。这些误检可能会对开发者的生产力产生负面影响 [1-3]。
DL 的近期突破在软件工程(SE)领域引起了广泛关注,促使人们探索其解决长期问题的潜力 [4, 5]。一些方法被提出以利用DL技术解决程序缺陷问题。一些突出的例子包括 DLFix [6] 和 DeepRepair [7],它们利用DL直接修复这些缺陷。CURE [8] 使用一个基于源代码语料库训练的DL模型来解析、分析和建模代码结构。DEAR [9] 则采用混合方法,将基于频谱的故障定位与DL结合,以增强对代码上下文的理解。需要认识到的是,每种方法都有其优缺点,因此需要进一步研究以确定基于DL的程序缺陷缓解策略的最佳方案。
然而,由革命性的transformers架构驱动的大型语言模型(LLMs)的兴起,极大地改变了自然语言处理(NLP)领域的格局,开启了能力与应用的新时代,并带来了前所未有的进步 [10-12]。最近的研究表明,LLMs在检测软件漏洞方面的有效性有时甚至超过了DL和传统方法 [12]。
1.1 问题陈述(挑战)
随着软件漏洞变得愈加复杂且易于利用,人们对组织防止数据泄露的能力以及个人保护其数字资产的能力愈发担忧。《2023年Verizon数据泄露成本报告》显示,公司通常需要197天才能识别出安全漏洞,并额外花费69天加以控制,这突显了快速有效的事件响应策略的必要性 [13, 14]。延长事件响应时间会使公司面临严重的财务和运营挫折,包括计划外停机和生产力下降。计算机处理和解释大量语言数据的需求,特别是在自然语言交互和软件漏洞管理任务(如识别软件代码中的缺陷)中,变得至关重要 [13, 15]。
传统的漏洞检测方法依赖于人类专家定义弱点,既缓慢又繁琐,因此对自动化工具的需求日益增长。于是,我们决定着手开发一种新方法,利用LLMs检测和修复软件漏洞。然而,缺乏全面的手册或既定指南为这一创新路径带来了重大挑战。这引发了许多问题,不仅涉及LLMs的应用和潜在方法,还包括所需和可用资源。本文提出的研究问题作为基础性探究,是启动我们专有方法论开发的必要条件,回答这些问题标志着我们工作的开始。本综述的目标是系统地解决这些问题,为对该领域感兴趣的研究人员提供有价值的资源。我们希望这篇文章能像对我们一样有益于未来的研究人员。
为了全面概述LLMs在软件漏洞领域的应用,理解这些模型当前如何应用、面临的挑战及其潜力尤为重要。因此,我们旨在对LLMs在该领域的应用进行系统的文献综述。本研究旨在回答以下研究问题:
1.2 研究问题
- RQ1:为什么我们应该使用LLMs进行软件漏洞检测?
- RQ2:LLMs在软件漏洞检测和缓解中可以发挥哪些作用?
- RQ3:在软件漏洞检测中已使用了哪些特定类型的LLMs?
- RQ4:与传统方法和工具相比,LLMs在检测和处理软件漏洞方面的表现如何?
- RQ5:LLMs已被应用于软件漏洞检测的方式有哪些?
- RQ6:微调LLMs对其在软件漏洞检测和修复中的表现有何影响?
- RQ7:用于微调LLMs以检测软件漏洞的技术有哪些?
- RQ8:用于训练、微调或测试LLMs以应对软件漏洞的数据集有哪些?
- RQ9:评估LLMs应对软件漏洞时使用的指标是什么?
- RQ10:在软件漏洞检测中使用LLMs的挑战是什么?
- RQ11:如何提高LLMs在软件漏洞检测中的有效性?
1.3 研究目标
通过回答上述问题,我们力求实现以下目标:
- 建立基础理解:为LLMs、其各种架构及其在软件安全领域的潜在应用提供清晰的介绍。
- 分析现有研究:回顾有关LLMs在软件漏洞检测中应用的现有文献。此分析将涵盖所用数据集、开发框架以及通过既定指标衡量这些方法的有效性。
- 识别研究空白与机会:通过批判性评估现有研究,旨在识别当前方法存在局限性的领域。这将突出未来研究工作的有前景方向,推动LLM解决方案在漏洞管理中的发展。
- 为未来研究提供指导:为研究人员提供实用见解和建议,以有效利用LLMs进行软件漏洞管理研究。这包括数据集选择、框架开发和性能评估的考虑因素。
通过实现这些目标,本文旨在成为进入这一令人兴奋且动态领域研究的宝贵资源。我们希望加深对LLMs在漏洞管理中能力的理解,并鼓励开发新颖且更有效的解决方案,以实现更安全的数字环境。
1.4 概述
在接下来的部分中,我们将首先详细说明用于收集和分析原始材料的方法。随后是一个全面的背景部分,深入概述LLMs、其类别及其在软件工程(SE)领域的应用。特别强调其在软件漏洞检测中的相关性,突出其优势和潜在局限性。
接下来将呈现一个对比分析表,将LLMs与既定的软件漏洞检测方法进行对比。该表格将阐明每种方法的相对优势和劣势,提供关于LLMs如何补充传统方法的更清晰视角。希望将LLMs与现有漏洞检测技术集成的研究人员会发现此表尤为有益。这种彻底的对比对于推动该领域的发展以及促进更强大、混合的软件安全方法至关重要。
接下来,我们将探讨在有效使用LLMs进行软件漏洞管理时面临的挑战。这些挑战包括与训练数据质量、计算资源需求以及模型泛化能力相关的问题。解决这些问题将有助于更清楚地识别当前研究中的空白,并为需要进一步发展的领域提供洞见。
最后,本文将以总结我们的发现和对未来研究的建议结束。我们的目标是提供对如何将LLMs整合到软件安全实践中的全面理解,以期改善现代软件系统中漏洞的检测和缓解。
2 方法论
为了全面探索大型语言模型(LLMs)在检测和处理软件漏洞中的应用,我们进行了系统的文献综述。以下步骤概述了所采用的方法论:
2.1 关键词识别
本研究由一个两人研究团队完成。初始研究阶段涉及通过Google Scholar进行搜索,使用两组关键词:“大型语言模型 Large Language Models ”分别与“软件工程 Software Engineering”或“软件安全 Software Security”结合。搜索结果以文献 [16] 和 [17] 为主要来源,从中提取了后续关键词。
以下是从两篇主要文章中提取并用于识别后续文章及指导搜索过程的关键词:基于transformers的双向编码器表示(BERT)、FalconLLM、预训练模型、网络威胁检测、软件修复、安全测试、渗透测试、软件漏洞检测、代码语言、大规模代码语言、预训练transformers、NLP、ChatGPT、GPT-4、Bard、代码生成、漏洞发现、transformer、过拟合、提示(Prompt)、代码分析。
arXiv、IEEE、Science Direct和ACM数字图书馆被选为下一阶段搜索的主要来源。我们在上述四个数据库中的最终搜索共产生了59篇文章。两位研究人员仔细审查了搜索结果,重点关注标题、摘要和关键词,以筛选符合研究目标的文章。从59篇文章中,最终选择了51篇,排除了8篇。
排除的8篇文章因不符合研究范围和目标而被剔除。其中一些文章专注于与软件漏洞检测或软件工程无关的一般机器学习或自然语言处理任务,另一些则仅提出了纯粹的理论框架,缺乏实际应用或相关实证证据。此外,部分文章过于具体且深入,涉及超出本研究重点的小众主题。这种细致的筛选确保了只有对理解LLMs在软件安全和工程领域有贡献的研究被纳入最终选择。
2.2 初步搜索结果的审查
在初步筛选之后,剩余文章由两位研究人员进行了严格评估,以确定其最终入选资格。为了减少偏见并提高审查的可靠性,采用了双重审查流程。每篇文章均由两位研究人员独立审查,以确保一致性和准确性。以下标准被应用于每篇文章。即使只符合一条排除标准,该文章也会被排除出进一步考虑。在此阶段结束时,共有四十篇文章被选中进行进一步分析。
纳入标准:
- 包含在其框架中使用LLMs进行软件漏洞检测的文章。
- 探索利用LLMs完成程序修复任务的文章。
- 探讨LLMs的各种用例的文章,例如代码生成、代码补全、调试、开发、测试和维护。
- 提供关于使用LLMs进行软件漏洞检测和处理的方法论及实现细节的全面描述的文章。具体而言,这些描述应涵盖:
- 所使用的LLM架构,包括模型规模、预训练数据和微调过程。
- 用于评估LLM在漏洞检测和处理方面有效性的特定数据集或基准。
- 清晰解释用来评估LLM在此背景下性能的指标或标准。
- 应用于LLM以增强其在软件漏洞任务中的适用性的任何新颖技术或调整。
- 提供关于两个主要关键词组合之一(“大型语言模型”与“软件工程”或“软件安全”)的文献综述的文章。“全面”综述定义如下:
- 涵盖广泛的相关研究,包括基础性工作和近期工作。
- 讨论该领域的研究演变,识别关键趋势、空白和挑战。
- 对不同方法、方法论和技术进行批判性分析。
- 包括补充材料(如数据集或代码)的文章。尽管补充材料(例如数据集、代码库或详细附录)备受重视,但并非强制要求。如果文章能提供与LLMs在软件漏洞缓解框架中的使用相关的实质性理论、方法论或实证贡献,则仍会被考虑。
- 被已选文章引用并提供对我们的研究具有重要意义见解或数据的文章。“附加信息”指:
- 已选文章未涵盖的新方法、框架或途径。
- 补充已选文章研究结果的进一步实验结果或案例研究。
- 提供对已选文章主题的不同视角的比较分析或批评。
排除标准:
- 非学术或非专业来源,例如博客文章或宣传材料,除非它们提供了其他学术文献中无法获得的可验证的独特见解。“独特见解”必须:
- 基于内部知识,例如来自行业从业者的与LLMs和软件漏洞检测直接相关的细节。
- 有实证证据、数据或案例研究支持。
- 在其他学术或同行评审来源中无法获得。
- 未能直接有助于解决研究问题或目标的来源。
- 排除与研究相关的信息不足或不清晰的来源。“不足”信息指那些在方法、结果或分析中缺乏必要细节以支持其结论的文章。“不清晰”信息指那些数据、方法或论点以模棱两可、不可复制或解释不清的方式呈现,难以评估其在LLMs和软件漏洞检测研究中的相关性或有效性。
- 排除非英文发表的文章。
- 如果无法获取论文全文,则将其排除。
2.3 滚雪球技术
我们从选定的文章中开始数据提取,并采用滚雪球技术扩展数据集。通过系统检查这些初始文章的参考文献列表,我们识别并纳入了68篇额外的相关研究。
2.4 批判性审查
选定的文章经过了批判性审查,重点在于提取关键见解、方法和研究发现。我们对研究质量进行了评估,以确保纳入稳健且相关的贡献。选定文章经历了一个严格的批判性审查过程,包括多个阶段的分析。首先,文章根据其与研究目标的相关性和一致性进行评估。随后,每篇文章都被仔细分析,以提取关键见解、方法和发现。这一过程包括对作者采用的研究设计和分析方法进行全面检查。这种全面的评估确保了只有高质量且相关性强的研究被纳入,从而增强了综述的可靠性和可信度。
2.5 综合与整合
从选定文章中获得的信息进行了全面综合,旨在识别现有文献中的总体主题、反复出现的模式以及知识空白。这些发现构成了本研究论文后续部分的基础框架。
2.6 人工智能(AI)辅助的使用
为了加快识别未解决问题的相关文章,我们使用了Microsoft Copilot、ChatGPT 4.0 和 Gemini 等工具。我们制定了以下提示语来查询 arXiv 或 ACM 等数据库:
“请提供一份来自 [数据库] 的文章列表,以帮助回答以下问题。问题是:……”
这种方法使我们能够利用人工智能的能力和 arXiv.org 的广泛数据库来填补研究中的任何空白。
2.7 引用与参考文献
所选文章均被正式引用,确保对来源的适当认可,并将其列入论文的参考文献部分。
2.8 审查过程中的潜在偏见
为确保全面且无偏见的审查,我们的选择并未局限于仅报告在软件漏洞检测和处理中使用LLMs取得积极结果的论文。通过纳入具有多样化结果的研究,我们力求呈现该领域当前研究状况的平衡视角。
3 背景
3.1 大型语言模型简介
什么是LLM?LLMs是预训练语言模型(PLMs)的一个子集,它们在大量文本数据上进行训练。LLMs的例子包括 GPT-4 [18]、BERT [19]、FalconLLM 系列 [20, 21] 等。这些模型在各种自然语言处理(NLP)任务中表现出卓越的能力,并基于神经网络架构,尤其是深度学习(DL)[19, 22] 构建而成,成为当前人工智能模型领域的最先进技术。术语“LLM”用于根据模型规模区分语言模型,特指大型的PLMs。然而,关于LLMs的最小参数规模尚无正式共识,因为模型的能力与数据规模和总计算资源密切相关 [16, 23, 24]。
凭借其庞大的训练数据集、复杂的神经网络结构以及先进的语言能力,LLMs 展现出在模仿、生成和微调自然语言方面的卓越能力。开发者使用大量的文本数据来训练LLMs,涵盖多种语言风格、领域和主题。这种训练过程使LLMs能够培养出对语言的统计理解,生成连贯且上下文感知的文本,并在各种NLP任务中表现出色。LLMs 中庞大的神经网络包含数百亿甚至数千亿个参数,使其能够识别细微的语义联系并在不同的语言任务中实现有效的泛化。LLMs 的规模和架构增强了它们容纳广泛语言知识的能力,展现出一种反映其训练数据的人工创造力 [25]。
此外,LLMs 在许多现实世界任务中得到了应用,例如机器翻译、内容创作、聊天机器人和事实主题摘要。尽管这些模型具备令人印象深刻的能力,但必须注意它们可能从训练数据中继承的潜在偏见,并需要负责任地开发。LLM研究领域正在快速发展,不断努力改进其能力、解决局限性并探索新的应用场景 [25]。
3.2 LLMs 的分类
当今最强大的LLMs 基于Transformer架构构建,该架构于2017年首次提出 [26]。根据具体应用,Transformer 模型可以配置为仅编码器(如 BERT)、仅解码器(如 GPT),或编码器-解码器网络(如 T5)。此外,稀疏模型代表了最近的一项创新,能够更高效地处理非常大的序列 [10, 16, 27]。
3.2.1 仅编码器
仅编码器模型擅长理解和总结输入序列中的信息。它们不生成新序列,而是生成固定大小的表示,适合分类等任务。尽管它们在需要全面理解的任务(如系统级芯片(SoC)安全验证)中表现优异,但它们无法基于所学上下文生成输出,限制了其在需要进一步生成的应用场景中的使用 [10, 23, 28–30]。
LLMs,特别是仅编码器类型的模型(如 BERT 及其变体),专注于对输入句子进行编码以捕捉单词关系和上下文信息 [16, 19, 23, 29]。
BERT 基于 Transformer 编码器架构,以其双向注意力机制著称,该机制在训练过程中同时考虑左右上下文。专门针对软件工程(SE)任务设计的模型,如 CodeBERT、GraphCodeBERT、RoBERTa、ALBERT、BERTOverflow 和 CodeRetriever,通过引入程序结构、新的预训练任务或结合不同模态,提升了其在代码相关任务中的应用 [16, 19, 23, 31]。
CodeBERT 通过预测后续标记来改进代码理解,有助于代码补全、代码搜索、错误检测和自动程序修复(APR)等任务 [16, 28, 31, 32]。GraphCodeBERT 利用代码元素之间的关系,将它们表示为图,从而在代码摘要、漏洞预测和程序分析等任务中表现出色。这些模型在代码审查、错误报告分析和识别代码结构中的实体等任务中尤为有效 [10, 16, 23, 28, 33]。
3.2.2 编码器-解码器 LLMs
编码器-解码器LLMs 是利用编码器和解码器模块的语言模型。编码器模块负责将输入句子编码到隐藏空间,而解码器用于生成目标输出文本。这种结构允许更灵活的训练策略 [30]。2017年提出的Transformer模型是这种架构的典型实现,由两个独立的Transformer块堆栈组成,分别充当编码器和解码器 [26, 27]。
编码器-解码器模型如 BART、PLBART、T5、CodeT5、AlphaCode 和 CoTexT 在摘要、翻译和问答等任务中展现了灵活性 [10, 16, 23, 27–29]。
3.2.3 仅解码器 LLMs
仅解码器LLMs 仅使用解码器模块进行顺序标记预测,与编码器-解码器架构形成对比。GPT 系列模型(如 GPT-1、GPT-2、GPT-3、GPT-3.5、GPT-4、ChatGPT)、CodeGPT、InstructGPT、Codex、Copilot、GPT-J、GPT-Neo、GPT-NeoX、LLaMA 和 Vicuna 都采用这种架构。它们在下游任务中无需额外的预测头或微调即可表现出色,因此成为SE任务中的宝贵工具 [16, 23, 28]。仅解码器LLMs 在众多NLP任务中建立了令人印象深刻的基准,尤其是在自由形式文本生成方面 [10]。
2022年,仅解码器LLM 的开发激增,并在2023年随着谷歌、Meta 和微软等公司推出 Bard、LLaMA、Llama 2、Bing Chat 等产品进一步加速。这些较新的模型尚未在SE中得到广泛应用,但在特定任务中具有未开发的潜力。仅解码器架构的持续进展表明了这一领域的积极探索与创新。
3.2.4 稀疏模型
稀疏模型,尤其是受混合专家方法启发的模型,正成为LLM架构中一个重要的进步领域。这些模型专注于为每个输入激活选定的参数子集,从而在不牺牲模型容量的情况下提高计算效率。与密集模型中每个输入激活所有参数不同,稀疏模型(尤其是基于MoE的模型)会激活特定的“专家”参数,这些参数针对每个输入量身定制。例如,Switch Transformer 和 GShard 展示了这种稀疏激活方法如何达到甚至超越密集模型的性能,同时需要更少的计算资源。在SoC安全领域,数据可能既庞大又复杂,稀疏模型在计算效率和任务特定准确性之间提供了宝贵的平衡 [10]。
每种LLM架构的独特能力和局限性突显了明智选择最适合模型架构的重要性。这种选择对于提升特定任务的精度至关重要。架构的选择应基于对任务具体需求以及可用LLM架构的优缺点的全面理解。
3.3 软件安全方法与漏洞检测方法的比较分析
鉴于理解软件漏洞检测领域的顶级和既定方法之间的区别和相似性的重要性,我们构建了表1以促进对这一主题的深入理解。我们创建此表的目的是系统地比较用于软件漏洞检测的各种方法,旨在突出它们的独特特征、优势和局限性。这种结构化的比较使人们能够清楚地了解不同技术的运作方式、在各种场景中的有效性,以及它们如何在综合安全策略中相互补充。通过组织关键标准(如目的、代码表示、适应性和主要使用场景),该表有助于评估哪些方法最适合软件开发生命周期中的特定场景或阶段。
该表的创建涉及对每种方法的深入分析,参考了学术文献、行业实践和工具文档。我们仔细研究了每种技术的功能机制、适应性、反馈机制和覆盖范围,并引用了权威来源以确保比较的准确性和可靠性。此表对考虑将LLMs与其他方法集成的研究人员尤为有益,因为它提供了全面的概览,有助于理解潜在的协同效应和互补功能。我们将在表后详细讨论表中所呈现的信息。
基于此表,我们可以看到动态应用安全测试(DAST)和交互式应用安全测试(IAST)都专注于在运行时测试应用程序。然而,它们的方法有所不同。DAST基于预定义规则运行,并模拟外部攻击,这使其适合于高层级的外部漏洞检测。相反,IAST结合了静态和动态分析,通过直接集成到应用环境中提供更具上下文敏感性的结果。这一差异使得当需要深入了解内部应用行为和漏洞时,IAST成为更优选择。
我们可以看到某些工具针对软件生命周期的特定阶段进行了优化。像手动代码审查和静态应用安全测试(SAST)这样的静态工具专注于开发早期阶段,提供了主动的漏洞检测方法。而像DAST、IAST和模糊测试这样的动态工具则更适合部署和运行时场景,展示了一种针对实时环境的反应性策略。这种区分突显了根据项目阶段战略性选择工具的重要性,以最大化效率和覆盖范围。
更深入的比较揭示了模糊测试和DAST等工具之间的重叠。模糊测试通过注入意外或随机输入来识别程序的异常行为,从而提供广泛的输入覆盖。而DAST虽然同样是外部测试,但专注于预定义的攻击模式和规则,因此不如模糊测试灵活,但更具针对性。需要检测高度特定漏洞的场景可能从DAST中获益更多,而模糊测试则擅长发现意外的边缘情况问题。这些工具之间的重叠表明,尽管它们可能解决类似的目标,但选择取决于具体需求,例如分析深度、适应性和所需的反馈类型。例如,当适应性和大规模应用是优先事项时,LLMs的表现优于手动方法。相反,在需要人类洞察上下文细微差别的场景中,手动方法更为优越。理解这些细微差别可以确保明智地选择和互补使用工具,以进行全面评估。
一个显著的观察结果是基于规则的工具与基于自适应学习的方法之间的差异。像SAST和DAST这样严重依赖预定义规则和模式的工具,在检测已知漏洞时提供了可靠的精确性,但缺乏现代学习型系统(如LLMs)的灵活性和广度。这些由AI驱动的解决方案因其能够在多种语言和场景中泛化的能力而备受关注,标志着向日益适应性和可扩展的安全方法的趋势。另一个关键事实是,对人类技能的依赖凸显了在大规模或时间敏感项目中应用时固有的可扩展性和一致性限制。这一限制与DAST和模糊测试等自动化工具形成鲜明对比,后者在高效执行重复任务方面表现出色,尽管上下文深度较浅。
这些工具的互补性成为一个核心主题。例如,SAST在检测源代码中的早期漏洞方面的精确性与DAST的运行时测试能力有效结合。它们共同创建了一个全面的安全态势,解决了开发阶段的问题以及部署期间出现的漏洞。同样,模糊测试和手动渗透测试可以协同工作,前者通过随机输入注入识别边缘情况异常,后者通过模拟利用场景验证这些发现。当工具按其主要方法分组时,其优势和局限性变得更加明显。像SAST和DAST这样的基于规则的工具因其清晰性、可重复性和效率而受到赞誉,但在处理新颖或未预见的漏洞时表现不佳。相比之下,像LLMs这样的自适应工具提供了显著的灵活性,随着时间的推移学习以弥补静态方法中的空白。然而,这些自适应解决方案并非没有缺陷,可能会产生误报或需要大量的计算资源。
关于反馈机制的模式也逐渐显现。LLMs提供迭代性和解释性反馈,促进了对问题的深入理解和解决。相比之下,模糊测试和DAST更加自动化,提供简洁的报告,但可能需要额外的解释。这种差异突显了根据项目的具体目标平衡自动化和可解释性的必要性。
另一个值得关注的点在于工具之间代码表示的差异。一些工具(如SAST和手动代码审查)分析源代码,能够直接在代码库中识别结构性和逻辑性缺陷。而其他工具(如DAST和模糊测试)则专注于输入和运行时行为,完全绕过了对源代码访问的需求。这种差异使得运行时工具在无法获取源代码的情况下(例如测试第三方应用程序或在黑盒环境中评估API)变得不可或缺。该表还强调了泛化能力的差异。像LLMs和模糊测试这样的工具展示了高泛化潜力,使其在不同语言、模式和应用中具有多功能性。相比之下,像DAST这样的基于规则的系统在预定义场景中表现出色,但在遇到新出现的威胁时则显得力不从心,进一步突显了对自适应技术日益增长的需求。
这些工具的相互作用强调了综合方法的重要性。没有任何一种方法能够全面解决所有漏洞;相反,它们的组合使用可以发挥各自的优势,同时弥补弱点。因此,该表不仅按功能对工具进行分类,还为设计多层面、有效的测试策略提供了蓝图,以应对复杂的现代应用。
3.4 软件开发生命周期(SDLC)中的大型语言模型
安全漏洞通常在软件开发生命周期(Software Development Life Cycle,SDLC)的构建阶段被引入,但直到在运营阶段导致安全故障时才变得明显。这种延迟检测可能导致修复成本增加、公司声誉受损,甚至对应用程序造成潜在的不可逆损害。为了降低这些风险,在SDLC的所有阶段采用专门的漏洞检测工具至关重要 [53]。
鉴于此,我们鼓励其他研究人员探索将LLMs集成到SDLC各个阶段以检测和处理软件漏洞的可能性。SDLC可分为六个阶段 [16]:
- 需求工程 Requirements engineering;
- 软件设计 Software design;
- 软件开发 Software development;
- 软件质量保证 Software quality assurance;
- 软件管理 Software management;
- 软件维护 Software maintenance。
在SDLC的背景下,LLMs在第3阶段(软件开发)、第4阶段(软件质量保证)和第6阶段(软件维护)中对检测和管理软件漏洞尤为有价值。然而,由于其巨大的潜力,LLMs的用途不仅限于这些阶段。此外,这一领域仍处于起步阶段,提供了广阔且尚未充分开发的研究和创新潜力。下表概述了各种LLM模型在SDLC不同阶段的应用(表2)。
4 RQ1:为什么我们应该使用LLMs进行软件漏洞检测?
随着企业越来越多地融入数字领域,网络威胁的形势也在迅速演变,变得愈加复杂和严峻。这种连通性的激增加剧了对强大网络安全措施的迫切需求。在这一挑战中,新兴研究表明自然语言处理(NLP)技术在加强网络防御机制方面具有潜力。具体而言,NLP应用在检测软件代码中的漏洞方面展现出希望,这是预防网络攻击的关键环节。众所周知,软件错误是恶意行为者发动网络犯罪的主要切入点。尽管技术有所进步,但软件漏洞的持续存在仍然显著,正如每年更新的通用漏洞披露(CVE)列表所显示的那样。传统的错误识别方法曾被广泛依赖,但由于其容易出现不准确和误诊的问题,现在正面临争议。这凸显了在日益互联的世界中采用创新方法(包括基于NLP的方法)以增强网络弹性的紧迫性 [13]。人工智能(AI)实时处理海量数据集、提取洞察并预测潜在威胁的能力,有可能彻底改变主动网络安全措施 [71]。通过使用像 GPT 这样的LLMs以及适当的数据库(例如软件保证参考数据集(SARD)基准数据集和 SeVC 数据集),我们可以分析不同编程语言(包括 C++/C 和 Java)中的薄弱代码 [72]。
虽然机器学习已被用于漏洞检测,但传统方法需要复杂且容易出错的手动特征工程来定义机器应分析的信息。深度学习方法(如卷积神经网络(CNNs)和循环神经网络(RNNs))已被探索,但它们需要特定格式的代码数据,这可能会带来挑战。于是出现了基于transformer的神经网络架构,这些架构因在自然语言处理领域的成功而闻名。目标是开发一种能够自动从各种编程语言中学习语法(结构)和语义(含义)信息的模型,为使用LLMs构建更强大的漏洞检测系统铺平道路 [13, 73]。此外,与RNN相比,基于transformer的语言模型因其在模型计算中的并行化能力而更具吸引力和前景,从而比RNN实现更快的处理速度。这一点对于减少大型模型(如基于transformer的模型)训练和测试所需的时间至关重要。此外,这些模型通过迁移学习从自然语言处理任务过渡到相关任务的能力,使其在各个领域的适用性得以扩展 [74]。
利用像 GPT-4 和开源模型(如 Llama)这样的基于transformer的模型进行漏洞检测可以带来诸多好处,包括更高的准确性和自然语言处理能力。这些模型消除了静态分析工具中手动输入的必要性,将检测过程简化为更快、更自动化的程序 [13]。
RQ1 回答:
由于大型语言模型能够跨多种编程语言自动识别代码漏洞,因此应该将其用于软件漏洞检测。它们提供了更高的准确性和自然语言处理能力,简化了检测过程,并且相比传统方法实现了更快的处理速度。
5 RQ2:LLMs在软件漏洞检测和缓解中可以发挥哪些作用?
5.1 代码分析与漏洞检测
LLMs可以被训练用于分析源代码并识别潜在漏洞。通过理解编程语言和常见的漏洞模式,LLMs能够标记不安全的编码实践,例如缓冲区溢出 buffer overflows [12, 17, 23, 24, 52, 72, 75–77]、SQL注入点 SQL injection points [12, 24, 38, 58, 61, 78, 79] 和错误处理 error handling [1, 38, 80],从而帮助开发者预先修复问题。
5.2 日志中的自动化威胁检测
LLMs可以处理来自服务器、应用程序和网络设备的大量日志数据,以检测可能表明安全漏洞的异常情况。通过识别模式和偏离正常行为的现象,LLMs能够在实时环境中帮助识别潜在威胁,从而实现更快的响应和缓解 [11, 70, 81]。
5.3 钓鱼邮件和网站检测
通过分析电子邮件的内容和结构,LLMs可以检测钓鱼攻击尝试。这些模型能够识别可疑元素,例如异常的发件人地址、误导性链接和欺骗性语言,从而在有害邮件到达最终用户之前进行过滤 [70, 81–85]。这一能力延伸到软件漏洞检测,因为钓鱼邮件通常作为利用软件系统安全弱点的载体,使LLMs在识别和缓解此类漏洞方面具有重要价值。
5.4 自动化补丁推荐与自动程序修复(APR)
利用LLMs进行自动程序修复(APR)已成为一个高度研究的领域,特别是在LLM技术取得最新进展之后。当检测到漏洞时,LLMs可以建议甚至生成修复该问题的补丁。通过理解代码上下文和漏洞的本质,LLMs能够提供精确的修改建议,供开发者实施以增强安全性 [8, 9, 17, 28, 34, 86–88]。
5.5 自然语言处理与事件响应
LLMs在解读安全报告和支持事件响应工作中发挥了关键作用。通过从冗长的安全报告和公告中提取关键信息,LLMs提供了可操作的见解和建议,使安全团队能够及时了解情况并对新兴威胁做出更有效的响应。在安全事件期间,LLMs还可以通过分析攻击向量、关联事件并提供对攻击者方法的洞察,帮助团队理解漏洞并实施有效的应对措施 [11, 27, 70]。
5.6 LLMs在SoC(片上系统)中的安全漏洞插入与检测
像 GPT-3.5 和 GPT-4 这样的LLMs可以通过遵循自然语言提示来识别并将潜在漏洞插入硬件设计中。这些模型检测安全规则违规行为,例如不可达状态或静态死锁,并精确定位硬件设计中的薄弱环节。通过分析设计逻辑,LLMs可以引入漏洞以进行测试,或者识别诸如重复编码等问题,从而助力预防性安全工作 [10]。这突显了LLMs在检测和处理安全漏洞中的关键作用,并将其应用扩展到软件漏洞检测和缓解范围内的硬件级漏洞。
5.7 LLMs用于渗透测试
研究人员探索了使用 GPT-3.5 等LLMs来增强渗透测试流程。LLMs被用于协助渗透测试人员进行高层任务规划和底层漏洞挖掘。具体而言,它帮助规划安全测试任务并分析易受攻击的虚拟机状态,以提出具体的攻击向量。这些建议随后被自动执行,展示了LLMs在增强人类专家识别和利用安全漏洞能力方面的潜力 [89]。
5.8 培训与模拟
LLMs可用于创建逼真的网络安全培训场景。通过模拟攻击和防御,它们可以帮助安全人员识别和应对威胁,提高整体准备度和韧性。
上述每个示例都展示了LLMs在增强软件漏洞和网络安全威胁检测与处理方面的不同应用。
RQ2 回答:
LLMs在软件漏洞检测和处理中的应用包括但不限于以下方面:代码分析与漏洞检测、日志中的自动化威胁检测、钓鱼邮件和网站检测、自动化补丁推荐与自动程序修复(APR)、自然语言处理与事件响应、培训与模拟。
6 RQ3 和 RQ4:LLMs在软件漏洞检测中的表现:模型及与传统方法的比较
本节回答两个关键研究问题:RQ3,在软件漏洞检测中已使用了哪些特定类型的LLMs? 和 RQ4,与传统方法和工具相比,LLMs在检测和处理软件漏洞方面的表现如何? 这两个问题将通过分析表3中的数据来回答。
为了回答这些问题并协助研究人员,我们编制了表3,详细列出了各种研究中使用的具体LLM模型、测试目的、实验结果以及对应的研究论文。该表为理解不同LLMs的应用方式及其与传统方法的性能比较提供了基础。这些研究中使用的数据集将在讨论RQ6的部分中详细阐述。
RQ3 回答:
在软件漏洞检测中已使用了多种类型的LLMs,包括:
- OpenAI 的 GPT 系列(GPT-3.5、GPT-3.5-turbo、GPT-4)
- LLAMA 模型
- BERT
- GraphCodeBERT
- SentenceTransformers 模型(all-mpnet-base-v2、all-distilroberta-v1、all-MiniLM-L12-v2)
- FalconLLM 系列
- CodeGen
- CodeBERT
- PLBART
- CodeT5
- JavaBERT
- Google-T5
- Mistral 模型等
这些LLMs在漏洞检测、恶意软件分类、代码摘要生成和代码生成等任务中表现出熟练能力,展示了其在网络安全研究和实践中的潜力。然而,表3也显示,结果并不总是积极的,即使是先进的模型有时也会表现出不到50%的准确率,这意味着一个简单的猜测机器可能都会胜过它们。这清楚地表明还有改进的空间,而对这些模型进行微调可能会显著提高其准确性和正面结果。
RQ4 回答:
表3表明,尽管大型语言模型(LLMs)在产生积极成果方面具有巨大潜力,甚至在某些情况下超越传统方法,但它们也面临一定的挑战和局限性。我们希望通过分析本节内容,研究人员能够受到启发,探索创新方法,并为推动这一研究领域的发展做出贡献。随着持续的进步,LLMs有望成为增强软件安全的宝贵工具。
7 RQ5:LLMs在软件漏洞检测中的应用方式
为回答这一研究问题,我们探讨了一系列研究,展示了LLMs在软件安全增强的各个方面的多样化应用。每项研究都提供了独特的方法,将LLMs集成到专门为漏洞检测设计的定制框架中。通过分析这些方法,我们可以全面了解LLMs如何有助于改进漏洞检测和缓解策略。
解释这些研究中使用的实验框架对于理解LLMs如何应用于增强软件安全至关重要。这些框架是LLMs运行的基础,并为结果的解读提供了有价值的背景信息。LLMs如何整合到更广泛的安全环境中对其性能有显著影响,而理解这一背景有助于验证结果。通过详细描述这些框架,我们可以清楚地看到每项研究的新贡献,包括使用LLMs如何提高准确性、加快威胁缓解速度或实现更高效率的自动化。此外,这一讨论还提供了比较性的见解,使读者能够在类似环境中评估不同方法的优势和局限性。
最后,通过详细说明实验框架,本节为未来的研究奠定了基础,为改进或扩展所讨论的方法论提供了潜在路径。无论是为了应对新型威胁,还是将LLMs的能力扩展到软件安全的其他领域,理解这些底层框架对推动该领域的发展至关重要。
LLMs用于自动程序修复(APR)(1)
在文章 [17] 中,LLMs被应用于软件漏洞检测,集成到一个自动代码修复框架中。在此框架中,LLMs用于生成经过边界模型检查器(BMC)初步验证或证伪后的修改代码。LLMs帮助识别诸如缓冲区溢出和指针解引用失败等软件漏洞,并提出修正补丁。这种验证与修复的迭代过程使LLMs能够有效应对漏洞,成功率达到80% [17]。图1展示了所提模型的框架。
该研究评估了超过1000个C程序,发现结合BMC和LLM可以有效检测和修复软件漏洞。这种方法在处理缓冲区溢出和指针解引用失败方面表现尤为出色,成功率达到80%。
GPT-4作为代码分析工具
实际案例 Real-world example 对于弥合理论研究与实际应用之间的差距至关重要。它们验证了方法的有效性,并提供了LLMs在现实世界软件安全环境中的表现洞察。通过研究基于LLMs的系统在识别和缓解漏洞中的实际应用案例,我们可以更好地了解其优势、局限性和实际意义。以下案例研究展示了一个具体示例,说明LLMs如何应用于检测和解决软件漏洞,并突出了其在增强网络安全措施方面提供的切实益处。一个现成的LLM显著例子是ChatGPT。
在 [12] 中,研究人员使用了OpenAI的7个LLMs(包括GPT-4)来检测和修复软件漏洞,采用了一种结构化流程。这项研究的意义在于其方法,避免了使用复杂框架、微调或对模型进行修改。这种极简主义方法为LLMs与其他软件漏洞检测方法和工具的固有效果提供了清晰的评估。
为了评估LLMs识别和修复安全漏洞的有效性,研究人员通过OpenAI API以特定指令(称为系统上下文)自动访问模型:
“充当所有主要编程语言的世界顶级静态代码分析器。我会给你一段代码片段,你将识别语言并分析其漏洞。输出格式为:文件名、漏洞列表(编号)、建议修复方案(单独编号列表)。”
“act as the world’s greatest static code analyzer for all major programming languages. I will give you a code snippet, and you will identify the language and analyze it for vulnerabilities. Give the output in a format: filename, vulnerabilities detected as a numbered list, and proposed fixes as a separate numbered list.”
这条指令引导模型检测代码中的漏洞、识别编程语言并提出修复建议。结果以清晰的格式返回,列出漏洞及其建议解决方案。
为了测试模型,研究人员提供了128个代码片段,涵盖八种广泛使用的编程语言,包括C、Ruby、PHP、Java、JavaScript、C#、Go和Python。这些代码片段旨在覆盖33种不同类型的漏洞,从缓冲区溢出到敏感数据暴露不等。许多示例(尤其是在PHP中)涉及文件包含和命令注入漏洞等问题。
为了比较LLMs与现有工具的性能,研究人员还使用知名静态代码分析工具Snyk分析了相同的代码片段。Snyk被软件开发人员广泛使用,提供有关漏洞的详细报告,并根据严重性(例如,关键或低风险)、是否可修复以及被利用的可能性对问题进行分类。通过使用Snyk,该研究旨在突出这些工具能够发现的漏洞类型,并将其与LLMs进行比较。在此,GPT-4识别了393个漏洞——几乎是GPT-3(213个)的两倍,是Snyk(99个)的四倍。这表明更大规模的模型更为先进,在需要理解和推理的任务中表现更好。值得注意的是,当GPT-4为这些漏洞提出修复方案时,它提供了398个具体的修正,展示了其不仅能够检测问题,还能提出可行解决方案的能力。
结果显示,GPT-4在减少漏洞方面非常有效。当使用Snyk分析由GPT-4修复的代码库时,高严重性漏洞减少了94%,中等严重性漏洞减少了75%,低严重性问题减少了92%。此外,GPT-4为项目增加了约11%的代码行数,这可能反映了安全检查和验证的引入以缓解漏洞。
该工具在所有编程语言中均表现出色,甚至能够在未明确告知的情况下正确识别每段代码的语言。这表明GPT-4或其他LLMs可能是自动化分析大型复杂代码库的宝贵工具。
为了更好地理解这一案例研究,我们将展示一个测试代码示例以及GPT-4和Snyk如何响应它。此示例突出了它们在识别和解决软件漏洞能力上的差异,为每种工具的优势和局限性提供了实际说明。
通过对一段Python代码的分析,我们展示了现实世界应用程序中存在的漏洞类型以及这些工具如何检测和解决它们。这一比较还强调了GPT-4超越单纯识别的能力,通过提供详细的解释和可行的修复方案,这对提高代码安全性至关重要。
LLMs用于自动程序修复(APR)(2)
如图2所示,Huang等人 [34] 提出了一种将LLMs应用于自动程序修复(APR)的工作流程,该流程由多个步骤组成,旨在增强模型理解并生成代码修复的能力。首先,数据预处理将原始源代码转换为适合LLM处理的格式,采用诸如代码抽象化和不同代码表示的技术,以增强模型对修复模式的理解。随后,模型训练和微调将LLMs扩展到神经机器翻译(NMT)架构中,重点关注编码器独占模型和编码器-解码器模型,因为它们在性能上表现优异。通过对数据集进行迭代训练,模型学习了缺陷修复的领域知识。在此过程中,通过多种指标评估检查点,以确定最佳的补丁生成模型。
在模型评估之后,补丁生成阶段采用束搜索(beam search)策略,从多个修复模型中合成补丁。使用测试用例过滤可能的补丁,并进行手动验证以评估生成补丁的正确性。这一验证过程有助于确保生成修复的准确性。总体而言,该工作流程旨在系统地探索预处理技术、模型架构、评估指标和补丁生成策略,以增强LLMs在自动程序修复中的能力。
论文表明,在NMT微调范式下,大型代码语言模型(LLMCs)在各种场景中展现了强大的修复能力。即使未采用后处理策略,LLMCs也取得了令人印象深刻的结果,超越了许多现有的APR方法。
漏洞修复解决方案
文献 [87] 提出的漏洞修复框架围绕利用预训练编程语言模型(如CodeBERT和GraphCodeBERT)来处理代码中的单行和多行安全漏洞。该过程首先构建一个包含漏洞代码及其对应修复方案的数据集,称为错误修复对(BFPs)。这些BFPs作为微调预训练PL模型的训练数据。
模型选择阶段对于选择适合此任务的PL模型至关重要。作者选择了CodeBERT和GraphCodeBERT,因为它们能够处理多种编程语言并结合特定于编程的功能,例如GraphCodeBERT中的数据流信息。然后,系统在漏洞修复的下游任务上进行微调。
在微调过程中,模型学会根据漏洞代码输入生成修复方案。在测试阶段,漏洞代码片段被输入模型,模型预测修复后的代码。模型的性能通过双语评估替代分数(BLEU)进行评估,这是一种常用于评估机器生成文本质量的指标。在BLEU得分最高的模型被选中进行进一步测试。
GraphCodeBERT通过引入数据流图增加了额外的复杂性,该图提供了代码中不同变量之间关系的表示。这一特性在处理更复杂的多行漏洞时尤为有用,因为它使模型能够更有效地理解代码各部分之间的依赖关系(如图3所示)。
在结果方面,预训练PL模型表现出色,尤其是在单行漏洞修复任务中,CodeBERTFix达到了95.47%的准确率,GraphCodeBERTFix达到了94.04%。重要的是,这些模型在多行漏洞修复任务中也表现出色,其中GraphCodeBERTFix实现了90.06%的准确率,优于在多行漏洞修复任务中表现不佳的DLFix。GraphCodeBERT中使用数据流信息被证明是一个显著的优势,使其能够比其他模型更好地处理多行修复的复杂性。
尽管这些结果证明了预训练PL模型在漏洞修复中的有效性,但研究也指出了某些局限性。CodeBERTFix和GraphCodeBERTFix有时会生成语法错误的修复方案,例如缺少或多余的括号,并且在处理过长的代码段时存在困难。这些不足之处突显了进一步改进的必要性,特别是在确保结构完整性以及处理大规模代码问题方面。然而,使用PL模型(尤其是结合数据流信息)代表了自动化漏洞修复的一个有前景的方向。
VulDetect
文献 [13] 的作者介绍了一种名为VulDetect的分类模型,旨在利用大型语言模型GPT-2实现自动软件漏洞检测。VulDetect采用微调的GPT-2模型识别与目标源代码中提取的易受攻击代码段相关的向量。其NLP漏洞模型接受一个长字符串作为输入,通常是一个C源文件。在后续步骤中,分词器将字符串分割为单独的单词和子词。值得注意的是,句法字符(如句号、分号、括号和方括号)被视为独立实体。接下来,编码器将这些单词转换为向量表示。这些向量化单词随后以顺序方式(逐个标记)或更大块的形式输入模型。在实施这一漏洞检测技术的过程中,输出向量对应于训练数据集中存在的漏洞类别数量。具体来说,包含124个独特漏洞类别的数据集,其输出向量维度为124。该输出向量通过Softmax函数进一步处理,将其归一化为概率分布,所有概率之和为1。输出向量中的每个元素表示相应漏洞类别出现在分析代码文件中的预测概率。
在防御性能评估中,研究人员选择通过对三种分类器(GPT-2、CodeBERT和长短期记忆网络(LSTM))进行测试来评估其技术的有效性。这些测试使用两个标准化基准数据集:SARD和SeVC。目标是衡量其技术在检测漏洞方面的能力。
表4中的结果显示,采用VulDetect技术的分类准确率显著提高。值得注意的是,GPT-2分类器表现出最高准确率,在SARD数据集上的测试中达到了92.59%,而LSTM分类器的准确率最低,在SeVC数据集上的评估中仅为65.78%。总体而言,GPT-2始终优于其他架构(CodeBERT和LSTM),这与其作为基于transformer的模型的声誉相符,该模型在包括情感分析和句子分类在内的各种语言任务中表现出最先进的性能。
本文提出的漏洞修复解决方案框架围绕利用预训练编程语言模型(如CodeBERT和GraphCodeBERT)来处理代码中的单行和多行安全漏洞。该过程首先构建一个包含漏洞代码及其对应修复方案的数据集,称为错误修复对(BFPs)。这些BFPs作为微调预训练PL模型的训练数据。
VulD-Transformer
VulD-Transformer [95](如图4所示)是一个用于源代码漏洞检测的综合框架,包含四个主要组件:输入模块、代码解析器、漏洞检测器和输出模块。每个部分在检测过程中都起着关键作用。
输入模块
该模块接收源代码作为输入,并启动检测过程。
代码解析器
代码解析器根据特定的语法规则处理源代码,以生成代码片段(code slices),这些片段是包含潜在漏洞的代码段。此过程包括以下四个步骤:
- 使用Joern工具生成程序依赖图(PDG)。
- 根据预定义的语法规则,在PDG中识别漏洞候选者。
- 从识别出的漏洞候选者生成代码片段。
- 清理和规范化代码片段,去除无关字符并标准化标识符和变量名称。
漏洞检测器
漏洞检测器评估代码片段是否包含漏洞。它包括两个主要操作:
- 向量转换:利用FastText将代码片段转换为向量。FastText的字符级嵌入能够捕捉源代码中标识符之间的细微关系,从而提高检测准确性。
- 漏洞检测:漏洞检测器学习代码片段的向量表示,获取代码片段的全局特征,并在最后一层获得最终的漏洞检测结果。漏洞检测模型利用Transformer架构来学习代码片段的向量表示。在此模型中,仅使用标准Transformer结构的编码部分,而解码器(常用于自然语言生成的生成模型)未被使用。
该模型由以下几个关键组件组成:
- 位置编码:向代码片段向量添加位置信息,以保留其顺序信息。
- 多头注意力机制:通过计算相互注意力来捕捉代码标记之间的长距离依赖关系。
- 前馈层:由带ReLU激活的全连接层组成,用于从代码片段表示中提取更高级别的特征。
- 加法与归一化层:对注意力层和前馈层的输出进行加法和归一化处理。
- 带Softmax激活的全连接层:生成最终的漏洞检测结果,将代码片段分类为无漏洞或有漏洞。
在最后一步,漏洞检测结果呈现给用户,指示分析的源代码中是否检测到漏洞。
提出的VulD-Transformer模型在多个关键指标上表现出卓越性能。
- 在合成数据集中:与VulDeePecker、SySeVR-BGRU、SySeVR-ABGRU和Russell相比,该模型在准确率上平均提高了6.12%,召回率提高了8.01%,F1分数提高了7.63%,尤其是在长度超过256个标记的代码片段中表现尤为突出。
- 在真实漏洞数据集(Devign和REVEAL)中:VulD-Transformer分别实现了59.34%和80.44%的检测准确率,优于对比方法。
RQ5 回答:
我们展示了大型语言模型(LLMs)可以通过多种方式应用于软件漏洞检测。这些方式包括但不限于将其集成到自动代码修复框架中以检测漏洞。LLMs还可以用作代码分析工具,显著优于传统工具,能够识别更多漏洞并提供详细的修复建议。此外,包含LLMs的框架(如VulDetect)在漏洞分类方面表现出色,准确率高达92.59%。LLMCs还可应用于单行和多行漏洞修复,并取得了优异的结果。总之,大型语言模型(LLMs)具备集成到现有软件漏洞检测框架中的能力,或者成为新框架的核心组件。
8 RQ6:微调LLMs对其在软件漏洞检测和修复中的性能有何影响?
微调是指将一个原本在大规模通用数据集上预训练的模型,通过在较小的任务特定数据集上继续训练,以适应新任务或相关任务的过程。微调使我们能够利用模型现有的知识并在此基础上进一步提升性能,从而缩短训练时间并增强效果。
如果用于初始预训练的数据与目标任务所选数据集密切相关,则可以显著提高模型对该任务的理解和执行能力。例如,如果我们希望微调一个模型用于软件漏洞检测,而该模型最初是在大型代码相关数据集(如GitHub代码库)上进行训练的,那么它已经具备了相关的基础知识。这使得模型能够更好地识别和修复漏洞,从而使后续的微调过程更加高效且有效 [96]。
此外,并非所有领域都有足够的大规模数据集可供从头开始预训练模型,创建此类数据集可能耗费时间和资源。因此,一种有效的解决方案是尝试从小型数据集中获得最大收益。但问题仍然存在:微调是否总是能带来改进?为了回答这个问题,我们将分析一些研究,这些研究测试了微调LLMs对软件漏洞检测或缓解的影响。
我们将通过对学术论文的文献综述来探讨这一问题,这些论文明确测试了微调对LLMs的影响,或通过分析其他论文讨论了这种影响。
Ferrag等人 [75]
Ferrag等人通过对FalconLLM基础模型进行微调,创建了专门用于检测C代码中软件漏洞的SecureFalcon模型。这一微调过程显著提高了模型的准确性,在识别漏洞方面达到了94%的成功率。微调解决了深度学习方法中常见的问题,如模型不足和数据不平衡,这是通过对数据进行仔细预处理并充分利用FalconLLM的优势实现的。该研究使用了一个新的数据集FormAI,这对模型的训练和评估至关重要。此外,微调后的模型被集成到一个系统中,该系统不仅能够检测漏洞,还能建议修复方案,为开发者提供了宝贵的见解。
Huang等人 [34]
Huang等人进行了一项研究,全面评估了在微调范式下LLMCs(大型代码语言模型)的程序修复能力。研究人员旨在探索LLMCs是否能够有效修复更复杂的错误,例如多区域错误(multi-hunk bugs),这些错误此前尚未得到广泛研究。他们选择了五种流行的LLMCs——CodeBERT、GraphCodeBERT、PLBART、CodeT5和UniXcoder,并在涉及Java、C/C++和JavaScript编程语言中的错误、漏洞和缺陷的典型程序修复场景中进行了测试。
作者使用了多样化的数据集,并精心选择方法对LLMCs进行微调以用于自动程序修复(APR)。对于微调,他们依赖于广泛使用的错误修复对(bug-fix pair, BFP)数据集,包括BFP-small(BFP S)、BFP-medium(BFP M)和SequenceR,这些数据集提供了方法级别的错误代码及其对应的修复方案。这些数据集包含各种单区域缺陷,使模型能够从大量精选示例中学习。对于多区域错误修复,研究使用了CPatMiner数据集。该数据集专门包括多区域缺陷场景,要求模型考虑多个错误位置之间的复杂依赖关系。针对漏洞修复,研究使用了VulRepair数据集,其中包含来自Big-Vul和CVEfixes等来源的C/C++安全相关缺陷。对于编程错误,研究使用了TFix数据集,其中包含注释的JavaScript错误修复对。研究结果表明,微调显著增强了LLMCs在程序修复中的能力,特别是在处理更复杂的缺陷(如多区域错误和安全漏洞)时表现尤为突出。微调方法使LLMCs在多种基准测试中超越了现有的最先进的APR工具,包括Defects4J和VulRepair数据集。
研究结果得到了强有力的数值证据支持,证明了微调后的LLMCs在解决软件漏洞和错误方面的有效性。例如:
- 漏洞修复准确率的提升:在VulRepair数据集上,CodeT5实现了64.71%的修复准确率,比基线工具VulRepair的44.67%提高了20.04%。其他LLMCs(如UniXcoder达到63.77%,PLBART达到60.90%)也显著优于VulRepair。
- 多区域缺陷的表现:在Defects4J V1.2上的复杂多区域错误中,UniXcoder比DEAR多修复了25个错误,而CodeT5则多修复了24个错误。这突显了微调后的LLMCs在处理复杂缺陷方面取得的重大进展。
- 错误修复基准结果:在TFix数据集上,CodeT5实现了60.62%的错误修复准确率,比基线TFix(49.30%)提高了11.32%。同样,UniXcoder达到了60.10%的准确率,展示了模型之间的一致性表现。
总体而言,这篇论文突出了微调对LLMCs检测和缓解软件漏洞能力的变革性影响,同时为未来的研究改进提供了实证指导。
Yang等人 [97]
Yang等人的论文研究了微调LLMs对检测和缓解软件漏洞的影响。该研究提出了一种名为多任务自指令漏洞检测(MSIVD)的方法,该方法结合了多任务序列到序列微调和图神经网络(GNNs),以增强模型识别漏洞的能力。MSIVD显著优于现有方法,并在处理未见过的漏洞方面展现出潜力。
MSIVD方法专注于多任务微调,利用代码片段和漏洞解释相结合的方式。这种微调策略提高了模型的泛化能力和准确性,在BigVul数据集上实现了0.92的F1分数,相比之下,基线LineVul的F1分数仅为0.81。此外,MSIVD模型达到了0.93的精确率和0.91的召回率,突显了其在识别有漏洞和无漏洞样本方面的平衡性能。这些指标证明了MSIVD的有效性,尤其是在同一数据集上,LineVul的召回率为0.78,精确率为0.86的情况下。MSIVD方法在与非LLM方法的比较中也表现出色。最佳的非LLM结果由DeepDFA(一种基于深度学习的方法,用于检测源代码中的函数级漏洞)实现,其F1分数为0.67,精确率为0.54,召回率为0.90。
当在PreciseBugs数据集上进行评估时,该数据集旨在通过排除现代LLMs训练数据中存在的漏洞来缓解数据泄漏问题,MSIVD实现了0.48的F1分数,优于LineVul的0.31。考虑到PreciseBugs的挑战性,这一改进尤为显著。例如,PreciseBugs包含2023年1月之后发布的漏洞,并具有更现实的漏洞类型分布。例如,PreciseBugs的平均样本大小为377行代码,而BigVul的样本平均为30行,使其成为更具挑战性的漏洞检测数据集。
研究表明,漏洞解释在微调过程中起到了关键作用。损失曲线分析显示,使用解释进行训练的模型表现出更稳定的训练动态,并避免了过拟合,即使在像BigVul这样可能存在预训练数据污染的数据集上也是如此。同样,在PreciseBugs数据集上,采用多轮自指令微调的MSIVD实现了更好的泛化能力,减少了对数据集中已有模式的过拟合。
F1分数的提升证明了将漏洞解释与多任务微调相结合的有效性。这种方法不仅使模型学会检测漏洞,还加深了对漏洞成因及潜在修复方案的理解,使其更适合在频繁出现新型和未见漏洞的真实场景中部署。
Guo等人 [94]
Guo等人进行了一项深入实验,分析了LLMs在软件漏洞检测中的能力。他们在六个专门为漏洞检测训练的开源模型与六个通用LLM(CodeBERT-base、Mistral-7b-base、Mixtral-8×7b-base、CodeLlama 7B & 13B、以及GPT-4-base)之间进行了对比实验。
研究突出了微调在漏洞检测任务中的上下文优势。微调后的模型通常在特定数据集上表现优于其预训练版本。例如,尽管最先进的模型在平衡和不平衡数据集上的F1分数通常在30%到50%之间,但本研究中所有微调模型在作者定制的数据集上表现显著更好。其中,CodeLlama-7b-fine-tuned实现了令人印象深刻的97%的F1分数,展示了微调在针对特定数据上下文时的变革潜力。
微调还显示出优化较小、资源高效的模型以实现与更大模型相当或更优性能的前景。这在微调较小模型(如CodeBERT-fine-tuned或基于VulBERTa的变体)时尤为明显,这些模型在没有大型商业LLM计算开销的情况下取得了竞争性结果。这种权衡使得低资源需求模型能够在受限环境中应用,强调了公开模型权重以进行任务特定微调的重要性。
用于微调的数据集质量是一个关键因素。作者观察到,微调模型的性能因所用数据集的不同而表现出显著差异,揭示了诸如错误标注和数据集不一致等潜在问题。例如,Choi2017和LineVul等数据集表现出不平衡或标注错误的问题,可能削弱微调的优势。作者使用Semgrep工具验证了这些问题,该工具在可靠扫描代码片段时面临困难,进一步强调了需要更精心整理的数据集以最大化微调效果。
尽管微调提高了特定任务的性能,但模型往往难以在多样化的测试环境中泛化。这一局限性与训练数据的质量和多样性密切相关,因为基于狭窄数据集训练的模型在应用于新环境时往往会表现出意外行为和分类错误。解决这些挑战需要强大的数据整理和基准测试,以确保微调模型在其训练领域之外仍保持可靠性。
作者建议探索量化和减少小型LLM参数数量的策略,以创建适合受限环境的资源高效微调模型。他们还强调了系统性改进数据集的必要性,以缓解错误标注等问题,从而确保通过微调训练的模型能够更有效地跨任务泛化。这些努力旨在增强LLM在软件漏洞检测中的实际适用性。
Shestov等人 [98]
Shestov等人研究了微调LLMs对软件漏洞检测的影响,特别是在Java源代码中的应用。研究人员专注于适应WizardCoder,这是一种基于StarCoder的最先进代码LLM。他们的方法包括优化训练方案并解决现实世界数据集中常见的类别不平衡等挑战。
作者使用了来自CVEfixes(一个手动整理的Java漏洞数据集)和VCMatch等来源的数据集。最终数据集被划分为不含简单负例(P3)的X1(样本对模型来说易于分类为负类,因为它们缺乏复杂性或模糊性)和含P3的X1,分别用于评估模型在平衡和不平衡条件下的性能。平衡数据集(不含P3的X1)包含1,334个样本,正负类分布均衡;而不平衡数据集(含P3的X1)具有1:34的严重正负类比例,反映了现实世界的挑战。
研究使用了WizardCoder,这是一种基于GitHub源代码预训练的130亿参数Transformer模型。它通过LORA(设置:r=8,alpha=32,dropout=0.05)进行微调以用于漏洞检测。方法包括通过优化关键超参数(如批量大小、学习率和训练轮次)来微调预训练模型,使用训练和验证数据集,并在测试数据集上评估最佳模型。这将130亿参数的模型压缩至仅2,500万参数,比CodeBERT更小。结果验证了LORA在内存限制下对LLM适应的有效性。
在平衡数据集(X1)上的实验结果表明,WizardCoder在漏洞检测任务中优于ContraBERT模型。结果显示,WizardCoder在ROC AUC和F1分数上均超过ContraBERT,分别为0.69和0.71,而ContraBERT为0.66和0.68。WizardCoder的性能提升可归因于其更大的模型容量(130亿参数)和在更大代码语料库上的预训练,使其能够捕捉代码中更细微的模式和漏洞。
对于不平衡数据集,WizardCoder继续保持优势,ROC AUC为0.86,F1分数为0.27,而ContraBERT分别为0.85和0.22。然而,由于高度偏斜的类别分布带来的挑战,改进幅度较小。通过使用焦点损失(focal loss)和样本加权的进一步优化带来了适度的收益,在特定超参数配置下,最佳ROC AUC达到0.878。
de-Fitero-Dominguez 等人
de-Fitero-Dominguez 等人 [99] 的论文研究了利用微调后的大型语言模型(LLMs),特别是 Code Llama 和 Mistral,来增强自动化代码漏洞修复的效果,目标是 C/C++ 漏洞。研究表明,与传统方法以及其他最先进的方法(如 VulRepair 和 VulMaster)相比,这些经过微调的 LLMs 在自动化漏洞修复领域取得了显著进展。
模型使用了两个知名数据集 Big-Vul 和 CVEFixes 进行微调,这些数据集来源于 CVE 数据库,涵盖了广泛的漏洞类型,总共提供了超过 9,000 个样本的综合数据池。研究特别关注数据污染问题,通过创建训练集和测试集无重叠的精炼数据集,确保对模型泛化能力的真实评估。
微调过程中采用了先进的技术,例如量化低秩适应(Quantized Low Rank Adaptation, QLORA),该技术结合了 4-bit 量化和可训练的低秩分解矩阵,以及 NEFTune,通过向嵌入向量添加噪声以正则化训练并提升泛化能力。
评估重点放在“完美预测”(Perfect Predictions)指标上,该指标仅在模型输出与参考解决方案完全匹配时才视为正确。结果显示,Mistral 在处理具有挑战性的未见漏洞场景中表现优于 Code Llama。在原始数据集上,Code Llama 的准确率分别为 37%(单波束)和 49%(5 波束),而 Mistral 的准确率更高,达到 49%(单波束)和 57%(5 波束)。在消除数据重叠的精炼数据集上,Code Llama 的准确率下降至 16%(单波束)和 23%(5 波束)。相比之下,尽管 Mistral 的性能也有所下降,但仍然优于 Code Llama 和其他基准方法,达到了 18%(单波束)和 26%(5 波束)。
值得注意的是,对于关键漏洞类型如“越界写入”(CWE-787)和“释放后使用”(CWE-416),Mistral 表现出了显著改进:
- CWE-787:在 53 个案例中修复了 15 个,相比之下 VulRepair 修复了 3/58,VulMaster 修复了 12/58。
- CWE-416:在 55 个案例中修复了 19 个,显著优于 VulRepair 的 1/60 和 VulMaster 的 6/60。
研究结果表明,在特定数据集上微调 LLMs 能够显著提升其应对漏洞的能力。精炼数据集的方法确保了评估的真实性和鲁棒性,揭示了以往研究因数据重叠而导致的潜在高估问题。此外,Mistral 的卓越表现突显了微调和创新训练方法在漏洞修复任务中的重要性。
RQ6 回答总结:
研究结果表明,通过对大型语言模型(LLMs)进行微调,可以显著提升其在软件漏洞检测与修复中的表现。这种方法利用预训练知识并将其适配到特定任务中,从而实现性能的飞跃。研究表明,经过微调的模型(如 SecureFalcon、MSIVD、CodeT5 和 Mistral)在准确性与效率方面均优于基线工具和预训练模型,并在各种基准测试中表现出色。
微调还使得规模较小、资源效率更高的模型能够取得具有竞争力的结果,同时提升了模型对未见漏洞的泛化能力——前提是数据集经过精心整理以缓解数据污染等问题。此外,诸如 QLORA 和 NEFTune 等先进技术进一步增强了模型的适配能力,为漏洞缓解提供了实用且可扩展的应用方案。
9 RQ7:用于软件漏洞检测的LLM微调技术有哪些?
预训练模型通常对语言和上下文有全面的理解。然而,它们通常需要专门的知识才能在特定领域中表现出色。虽然微调的成本通常低于预训练,但仍需大量资源以获得最佳结果。这引发了对参数高效微调方法(Parameter-Efficient Fine-Tuning, PEFT)的日益关注。微调LLMs面临两个主要挑战:一是微调过程的高成本,二是“知识截止”问题。在微调后,模型无法感知其最后一次更新之后出现的新威胁或漏洞。这种限制通常需要反复进行微调,以确保模型保持最新且有效 [10]。
在本节中,我们将探讨研究人员常用的一些微调技术,这些技术在增强LLMs在软件漏洞检测和缓解任务中的性能方面发挥了关键作用。这些技术对于将预训练模型适配到识别和解决软件漏洞的具体需求至关重要。微调LLMs的方法主要有六种,我们将在本节中简要探讨每种方法(图5)。
9.1 全量微调(Full Fine-Tuning)
全量微调涉及更新预训练LLM的所有参数,以使其适应新的特定任务。在此过程中,整个模型在新数据上进行训练,从而学习与当前任务相关的表示。全量微调提供了最大的灵活性,因为模型的每一层都针对新任务进行了优化。然而,它需要大量的计算能力、内存和处理能力。此外,它可能导致“灾难性遗忘” [100],即模型在过度专注于新数据时丢失了大部分预训练知识 [101]。
少样本微调(Few-shot Fine-Tuning) 可被视为全量微调的一种变体,适用于有限示例的情况。
Hu等人 [102] 指出了在特定任务中适配LLMs的挑战。像GPT-3这样的语言模型在大规模数据集上预训练以预测文本序列,但需要微调才能在特定任务(如文本摘要或自然语言到结构化查询语言(SQL)命令的转换)中表现良好。微调调整了模型的参数以适应每个新任务,但对于包含数十亿参数的模型来说,这一过程非常困难。这使得存储和部署多个版本的模型变得难以管理。为了解决这个问题,作者建议使用低秩方法来简化调整,减少需要更新的参数数量。
由于全量微调需要大量资源,这种方法在研究人员中很少用于软件漏洞检测和缓解任务。相反,许多研究人员通常选择更高效的微调方法,这些方法可以在不依赖大量计算资源的情况下实现有效的适配。
9.2 特征提取(Feature Extraction)
特征提取方法将预训练的LLM视为一个固定的工具,用于提取有用信息,在微调过程中保持其核心参数不变。只有最终层或模型的一小部分(通常是任务特定的分类器)在新任务数据上进行训练。这种方法利用了模型已经学到的通用知识,用它来分析新输入,而无需改变主模型。特征提取在计算上非常高效,所需的资源远少于全量微调。当新任务与模型原始训练任务相似时,这种方法特别有效。因此,它成为文本分类或情感分析等任务的流行选择,因为这些任务不需要大量数据来进行适配 [65, 103]。
9.3 多任务学习(Multi-Task Learning, MTL)
这种方法同时在多个相关任务上训练LLM,例如漏洞检测、解释和修复,旨在不仅识别漏洞,还提供对其的解释。这种方法可以提高模型在不同但相关任务上的性能 [36, 97, 104]。MTL受到人类学习的启发,其中从一项任务中获得的知识往往有助于学习另一项任务。在机器学习的背景下,MTL通过在任务之间共享信息使模型更好地泛化。通过优化多个损失函数(数学公式,用于评估模型预测与实际或预期输出之间的匹配程度),MTL允许模型从每个任务的独特信息中学习。每个损失函数代表模型需要改进的一个特定目标,例如减少分类错误、生成准确的文本或识别数据中的模式。通过同时关注多个目标,MTL帮助模型从不同任务中学习有用的信息,每个任务都与特定领域相关。这种方法对于处理广泛语言任务的LLMs尤其有价值 [104]。MTL的一个关键动机是解决每个任务标记数据有限的问题。在这种情况下,每个任务的可用标记数据不足以训练出精确的模型。MTL结合所有任务的标记数据,类似于数据增强,为每个任务创建更精确的模型。这种方法允许重用现有知识,并有助于降低各种学习任务的手动标注成本 [105]。
MTL与多种机器学习方法相关,例如迁移学习、多标签学习和多输出回归。然而,与专注于使用其他任务知识改进单一主要任务的迁移学习不同,MTL平等对待所有任务,并旨在提高所有任务的性能。迁移学习单向转移信息(从源任务到目标任务),而MTL促进所有任务之间的双向知识共享 [105]。
MTL可以涵盖不同但相关的领域、学习风格(例如监督学习和无监督学习)、目标(例如分类或文本生成)以及多级特征(例如标记级和句子级特征)。MTL还可以包括涉及不同类型数据的任务,例如文本和图像。此外,在多个领域或语言中执行相同任务可以被视为多个任务,这一概念在某些文献中被称为多领域学习 multi-domain learning,可以作为开发MTL模型的基础 [106]。
9.4 参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)
在当前的研究文献中,参数高效微调(PEFT)已成为一个关键主题,重点在于最小化可训练参数的数量,同时保持最佳性能 [23, 27]。Ding等人 [107] 表明,即使大幅减少可调参数,大多数参数高效微调方法通常也能达到与全量微调相当的性能。这些发现强调了通过参数高效微调技术有效适配大规模PLM的潜力 [107]。
参数高效微调Transformer语言模型的四种主要技术包括:
- 适配器调优(Adapter Tuning)
- 前缀调优(Prefix Tuning)
- 提示调优(Prompt Tuning)
- 低秩适配(Low-Rank Adaptation, LoRA)
这些方法通过仅调整模型的一小部分参数,减少了计算和存储需求,同时保持了模型的高性能。
9.4.1 基于适配器的微调(Adapter-based Fine-Tuning)
基于适配器的微调在较大的预训练模型中插入小型、可训练的适配器层,同时冻结模型的大部分参数。这些适配器是微调过程中唯一更新的部分,从而显著减少了需要优化的参数数量。适配器层是小型的任务特定模块,能够在不改变原始模型的情况下将预训练模型适配到新任务。这种方法在计算成本和内存使用方面非常高效,使其成为无法对整个模型进行微调的任务的理想选择。适配器可以并行或顺序插入模型架构中,为任务适配提供了灵活性。此外,这种方法还解决了微调中的“灾难性遗忘”问题 [23, 27, 108]。
9.4.2 前缀调优(Prefix Tuning)与提示调优(Prompt Tuning)
前缀调优和提示调优是轻量级且参数高效的微调方法,仅调整模型的输入空间,而不改变其内部参数。
前缀调优(Prefix Tuning)
前缀调优是一种轻量级微调方法,保留了预训练模型的大部分参数不变,仅调整少量额外参数。它通过在基于Transformer的语言模型的每一层添加任务特定的可训练向量(称为前缀)来实现。这些前缀类似于额外的标记,引导模型专注于任务相关的信息。与更新原始模型参数不同,前缀调优优化这些新增加的向量,这些向量在训练时单独初始化并保持主模型冻结。在文本生成过程中,前缀提供任务特定的调整,而模型的其余部分则以正常方式处理输入。这种方法允许以最小的计算和内存开销实现高效的任务适配 [27, 107, 109]。
一个可选的多层感知机(MLP)可用于将较小的矩阵转换为前缀参数,从而提高训练期间的效率和稳定性。一旦训练完成,仅保留优化后的前缀向量,使模型能够以最少的额外参数执行任务特定功能。前缀调优具有高度通用性,适用于自回归和编码器-解码器模型,并能增强各种规模模型的自然语言理解任务性能 [27, 107, 109]。
Xiang Lisa Li 和 Percy Liang [109] 的研究表明,通过前缀调优仅更新0.1%的任务特定参数,对于表格到文本生成任务非常有效。他们的结果表明,前缀调优不仅优于其他轻量级微调方法(如ADAPTER和FT-TOP2),而且在性能相似的情况下所需的参数减少了约30倍。当参数数量匹配(均为0.1%)时,前缀调优比ADAPTER在每个数据集上的BLEU评分平均提高了4.1分。即使与3%参数量的全量微调和ADAPTER相比,前缀调优仍表现出相当或更优的结果。这说明了前缀调优的帕累托效率,即以更少的参数实现更高的生成质量。
提示调优(Prompt Tuning)
提示调优是一种不同于传统微调或前缀调优的方法,因为它专注于优化语言模型输入层的任务特定提示嵌入(trainable prompt embeddings)。与调整模型的内部层不同,提示调优涉及学习连续嵌入(称为“软提示”),这些嵌入被附加到输入标记之前。这些学习到的嵌入引导模型针对特定任务的行为,而无需更改其核心参数。这种方法在参数效率方面具有显著优势。仅在输入层添加少量可训练参数,与全量微调相比大大降低了计算成本,因为后者会更新所有模型参数。这使得提示调优特别适合大规模模型,因为较少的参数允许高效训练,同时保持性能。提示调优在大型模型上表现出了竞争性结果。例如,在SuperGLUE基准测试中,使用T5-XXL模型的实验表明,采用软提示的模型可以达到与全量微调模型相当的性能。这种可扩展性表明,大型语言模型可以通过提示调优以最少的参数变化适配多种任务 [27, 107]。
提示调优的效果还受到软提示长度和初始化的影响。精心的初始化可以显著提升模型在下游任务中的性能,表明提示嵌入的初始配置在引导模型学习过程中起着关键作用。最佳初始化可以加快收敛速度并提高整体准确性。
提示调优的另一个关键优势是其跨任务的可迁移性。一旦软提示被有效初始化,它们通常可以通过最小的调整适配到新任务,使这种方法既通用又高效。这一特性在需要跨多个应用部署模型而无需广泛重新训练的场景中尤为有益。然而,提示调优的成功与模型容量密切相关。较大模型能够更有效地利用软提示,从而在任务特定性能上表现更好。这是因为较大模型具备更强的能力从软提示中捕捉复杂模式和关系,增强了其对各种任务的适应能力 [107]。
9.4.3 低秩适配(Low-Rank Adaptation, LoRA)
低秩适配(LoRA)是一种先进的微调技术,旨在提高LLMs适配特定任务的效率。在神经网络中,权重矩阵是编码学习表示的核心组件。标准微调涉及更新这些矩阵中的所有参数,这对于大型模型来说计算成本高昂。LoRA通过使用低秩近似表示权重矩阵所需的更新来解决这一挑战。在微调过程中,LoRA将权重更新分解为两个较小的可训练矩阵(记为AA和BB)的乘积,而不是直接修改权重矩阵。原始模型参数保持冻结状态,仅优化这些小矩阵,从而显著降低计算开销和内存需求,同时保留任务特定的适配能力。这种方法在需要微调大规模模型但面临资源限制的情况下特别有利,实现了计算效率与任务性能之间的平衡 [27, 102, 108]。
LoRA已广泛用于开源LLMs(如LLaMA和BLOOM)的参数高效微调。在这些研究中,LLaMA及其变体因其参数高效调优能力而受到广泛关注。例如,AlpacaLoRA使用LoRA对Alpaca进行了微调,创建了一个轻量版本 [27]。[98] 的研究人员将LoRA方法应用于WizardCoder模型,使用特定设置将模型大小从130亿参数显著减少到仅2500万参数,甚至比CodeBERT更小。实验验证了LoRA在内存受限条件下适配LLMs的有效性,表明LoRA可以在大幅减少参数数量的同时保持性能,使其成为资源有限环境的可行选择。
在LoRA中,Transformer模型中的每个密集层仅训练两个小矩阵,而原始模型参数保持冻结。这些矩阵近似了适配模型到特定任务所需的调整,与全量微调相比,将需要更新的参数总数减少了多达10,000倍 [102]。这种减少降低了训练期间的内存和计算成本,使得更容易在专门任务上微调大型模型。此外,LoRA不会增加任何额外的推理延迟。微调完成后,低秩矩阵可以与预训练权重合并,使模型在推理时表现得像完全微调的模型。这一特性对于在对延迟敏感的环境中部署LLMs至关重要,因为它避免了适配器层等方法常见的性能开销 [102]。
RQ7 回答:
用于软件漏洞检测的LLM微调技术包括全量微调、特征提取、多任务学习以及参数高效方法(如基于适配器的调优、前缀调优、提示调优和低秩适配(LoRA))。这些方法在计算成本和适配能力方面各有不同,其中参数高效技术提供了节省资源的替代方案,同时保持了性能。
10 RQ8:用于训练、微调或测试LLMs以实现软件漏洞检测的常用数据集有哪些?
为了全面且实用地回答RQ8,我们整理了一份在此领域中常用的详细数据集列表。我们专注于基于代码的模型,并仅包括对所有研究人员公开可用的数据集。唯一的例外是REFINEDWEB数据集 [21],它完全是基于文本的。然而,由于其相对较小的规模以及在该数据集上训练的FalconLLMs模型表现出色,我们选择将其纳入报告。这些数据集包括基于代码和基于文本的数据,每种数据在训练和微调LLMs以检测、预测和缓解软件漏洞方面都发挥了关键作用。对于使用LLMs检测和处理软件漏洞,结合基于文本和基于代码的数据集往往最为有效 [16]。
- 基于文本的数据集:对于涉及修复漏洞、理解代码和理解与漏洞相关的文本内容的任务至关重要。它们帮助LLMs掌握安全问题的背景,识别安全相关文本(如漏洞报告或安全公告)中的模式,并增强其生成安全代码或识别代码中漏洞的能力 [16, 28, 75]。
- 基于代码的数据集:对于LLMs理解和分析代码至关重要,尤其是用于识别代码库中的漏洞。这类数据集帮助LLMs理解软件代码的结构、逻辑和潜在缺陷,使其能够识别漏洞、提出修复建议,甚至生成安全代码 [16, 92]。
通过结合这些数据集,LLMs可以学习将文本信息(如安全公告或漏洞报告)与实际代码关联起来,这在网络安全中至关重要。理解漏洞被报告的背景以及它们如何在代码中表现出来,使LLMs能够更全面、更准确地支持漏洞检测、处理和潜在预防。
图 6 展示了将在以下章节中介绍的数据集完整列表。我们将本节分为两部分。在第一部分中,我们将介绍适合预训练基础模型的主要大型数据集。这些数据集通常规模庞大,覆盖广泛领域,因此非常适合为大型语言模型(LLMs)提供坚实的基础。它们使模型能够学习多样化的模式,无论是通用软件开发还是其他任务,并且通常在早期阶段用于培养 LLMs 所需的核心语言理解与代码分析能力。
在第二部分中,我们将介绍更加专业化、特别适用于微调 LLMs 以处理软件漏洞任务的数据集。与第一部分中的数据集相比,这部分数据集规模较小且更加聚焦。它们集中于特定的漏洞、代码安全问题和威胁模式,对于优化 LLMs 的精确任务(如漏洞检测、威胁分析和安全代码生成)至关重要。通过使用这些数据集进行微调,LLMs 能够对漏洞有更深入和细致的理解,从而更有效地应对专门的安全挑战。
这种结构确保了通过大型多样化数据集训练的模型可以进一步利用领域特定数据进行精化,以应对软件安全的复杂性。通过区分用于预训练的通用数据集和用于微调的专业数据集,我们旨在为提升 LLMs 在软件漏洞检测领域的性能提供清晰的路径。
我们对每个数据集的说明进行了结构化整理,包括其内容、与软件漏洞检测的具体相关性以及主要关联的学术参考文献(如果有的话)。此外,我们还提供了指向存储库和来源的直接链接,以便研究人员、开发人员和网络安全专业人士能够快速访问这些资源。这种详细的描述和便捷的访问方式有助于进一步探索和使用这些数据集。
10.1 第一部分:用于预训练大型代码语言模型(LLMCs)的基础数据集
在本节中,我们将介绍广泛用于预训练LLMs的编码任务的基础数据集。这些数据集由于其庞大的规模和多样性,对于构建LLMs的基本语言理解和代码生成能力至关重要。在这些数据集上进行预训练使模型能够学习编码和语言的一般模式,使其足够灵活,以便稍后微调以执行更具体的任务,例如软件漏洞检测。以下表格(表5)总结了每个用于预训练的数据集的最重要细节。每个数据集将在表格之后详细介绍。
10.1.1 CodeSearchNet
CodeSearchNet 是一个旨在促进语义代码搜索模型训练和评估的数据集,重点是根据自然语言查询检索相关代码的任务。该数据集包含从开源GitHub存储库中收集的6,452,446个函数,涵盖六种不同的编程语言:Python、Java、JavaScript、PHP、Ruby 和 Go。此外,该数据集为2,326,976个函数提供了自动生成的自然语言文档,将代码与描述性文本配对,以模拟现实世界的代码搜索场景。
CodeSearchNet 对于训练LLMs理解代码结构并将其映射到自然语言描述非常有价值。这种能力可以应用于通过解释与安全漏洞相关的查询来检测软件漏洞,并检索展示漏洞的相关代码模式。
关键组件:
- 数据划分:提供三种划分:训练集(Train)、测试集(Test)、验证集(Valid)。
- 语言:Python、Java、JavaScript、PHP、Ruby、Go。
- 内容:函数级别的代码示例,配有自然语言注释或文档。
- 引入年份:2019年。
CodeSearchNet 项目已被归档,导致托管数据集的S3存储桶被移除。为了解决这一问题,CodeSearchNet 数据集现在可以从Hugging Face下载(最后访问日期:2024年10月2日)。这一替代来源确保研究人员和开发人员仍能访问和使用该数据集。
10.1.2 The Pile (2020)
The Pile 是由EleutherAI引入的一个825 GB的数据集,用于训练大规模语言模型 [111]。它由22个高质量且多样化的子集组成,涵盖了学术文章、GitHub存储库、法律文本和公共论坛等多个领域的文本。该数据集特别适用于构建需要从多个领域获得强大理解的通用语言模型。它适合用于一般语言理解和生成任务(即语言建模),但对于专门设计用于理解生成编程代码的代码语言模型(code-based LLMs)可能不够全面或有效。
The Pile 还可以用作综合基准,评估模型的泛化能力和跨领域的知识。对于软件漏洞检测任务,The Pile 中的GitHub子集尤为重要。它包含大量代码语料库,使LLMs能够学习编程语言中的模式,识别潜在漏洞,并生成安全代码。此外,像Stack Exchange这样的数据集的加入使模型能够解释和响应与安全相关的查询,从而增强其从代码和文本数据源中识别漏洞的能力。
关键组件:
- 大小:825 GB(英语文本语料库)。
- 下载链接:Pile 数据集(最后访问日期:2024年10月2日)。
- 来源:包括来自Pile-CC、PubMed Central、Books3、OpenWebText2、ArXiv、Github、FreeLaw、Stack Exchange、USPTO Backgrounds、PubMed Abstracts、Gutenberg (PG-19)、OpenSubtitles、Wikipedia (en)、DM Mathematics、Ubuntu IRC、BookCorpus2、EuroParl、HackerNews、YoutubeSubtitles、PhilPapers、NIH ExPorter 和 Enron Emails 的数据。
- 语言:主要为英语,但包含一些多语言内容。
10.1.3 GitHub Code
GitHub Code 数据集直接来源于GitHub,并可通过Google的BigQuery获取。这是一个庞大的GitHub托管源代码集合,主要用于涉及机器学习的任务,特别是在软件相关应用中训练、微调和测试LLMs的任务,包括软件漏洞检测、代码补全、错误检测和其他代码分析任务。
GitHub Code 涵盖了各种各样的代码,从开源库到完整的软件应用程序不等。它包含了多样化的编码风格、项目结构和编程风格,使其适用于各种与代码相关的机器学习任务。通常在用于机器学习任务之前,会对该数据集进行预处理。这包括清理数据(例如删除个人信息、非代码文件)、按编程语言组织以及将代码标记化为适合模型的格式。
您可以从Hugging Face下载 GitHub Code 数据集(最后访问日期:2024年10月2日)。
10.1.4 CodeParrot
CodeParrot 是一个大规模的公开源代码数据集,主要用于训练和微调与代码相关的机器学习任务。该数据集专注于Python作为主要编程语言,特别是在开发像 CodeParrot 这样的GPT类语言模型时发挥了重要作用。这种模型旨在生成、补全和理解Python代码。CodeParrot 是Hugging Face生态系统的一部分,已成为在代码领域进行机器学习开发的重要资源。
CodeParrot 数据集通过Hugging Face的Datasets库公开可用(最后访问日期:2024年10月6日),开发者和研究人员可以下载并用于训练自己的模型。此外,还提供了一个名为 codeparrot-clean 的清理版本,其大小为50 GB。
10.1.5 The Stack
The Stack 数据集 [112] 是一个3.1 TB的许可开源代码集合,专门用于训练和评估LLMs在编码任务中的表现。该数据集包含从1.3736亿个GitHub存储库中下载的代码,时间范围为2021年11月至2022年6月,涵盖30种编程语言。为了减少冗余并提高模型训练性能,还提供了一个去重版本。
该数据集支持多种任务,包括代码生成、代码补全、错误检测和文档生成。它涵盖了广泛的编程语言,包括Python、Java、C、JavaScript、HTML、C++ 和 CSS等。其中,HTML(746 GB)、JavaScript(486 GB)、Java(271 GB)和C(222 GB)是最大的组成部分。
The Stack 仅包含自由许可的代码,例如MIT、Apache-2.0和BSD-3-Clause许可证,而GPL等要求特定规则的许可证被排除在外,以避免法律或道德问题。此外,有一个明确的数据管理计划,允许开发者通过填写表格并通过GitHub验证后将其代码从数据集中移除。
10.1.6 The Stack V1 和 V2
The Stack V1
Hugging Face上的 The Stack V1 数据集(最后访问日期:2024年10月6日)是一个包含来自各种存储库的大量源代码文件的集合。该数据集是BigCode项目的一部分,旨在开发LLMs以生成代码。The Stack V1 在升级后包含超过6 TB的代码,涵盖358种编程语言。
The Stack V2
The Stack V2 是大规模源代码数据集的重大发展,提供了广泛且多样化的自由许可代码集合。该数据集基于Software Heritage的庞大存档,并增加了额外的高质量来源,包括GitHub问题、拉取请求、Kaggle笔记本、Jupyter笔记本和代码文档。相比其前身 The Stack V1,The Stack V2 实现了显著的飞跃,支持619种编程语言,规模是前者的十倍。
这种广泛的编程语言覆盖使 The Stack V2 非常适合训练专注于代码生成、分析和补全的LLMs [113]。其主要用途是训练代码语言模型(Code LLMs),例如 StarCoder2。StarCoder2 模型的参数规模从30亿到150亿不等,使用此数据集执行多种任务,包括代码生成、补全、错误检测以及对代码执行的推理 [113]。
一个去重版本的 The Stack V2 数据集也已提供,总大小为32.1 TB。两个版本的 The Stack V2 数据集均可通过Hugging Face Datasets库访问(最后访问日期:2024年10月6日)。
10.1.7 The ROOTS
The ROOTS 数据集是BigScience项目的一部分,旨在开放和协作环境中训练LLMs。它是同类数据集中规模最大的之一,包含1.6 TB的文本数据。ROOTS 数据集的设计考虑了伦理和多样性,并被用于训练 BLOOM 语言模型。它包含59种语言的数据,其中包括46种自然语言和13种编程语言(如Java、PHP和C++)[114]。
ROOTS 包含两个主要部分:
- 62%的数据来源于社区选择和记录的来源。
- 剩余38%的数据来源于 OSCAR [115],这是一个经过预处理的网络爬取数据集。
这些来源由母语者精心挑选和审查,以确保数据的准确性和高质量。协作工作包括开放提交和竞争性活动(如黑客松),吸引了专注于NLP和机器学习的本地社区参与。这些举措收集了来自广泛参与者的贡献,最终形成了超过250个多样化语言数据来源。这种策略确保了数据集包含多种语言和丰富的语言特征。
从技术角度来看,ROOTS 提供了多语言文本数据和编程语言的复杂整合。这使得可以训练能够处理人类语言和编程代码的模型。ROOTS 语料库可通过BigScience Data在Hugging Face上的官方存储库访问(最后访问日期:2024年10月7日)。
10.1.8 RefinedWeb
RefinedWeb 数据集由Falcon LLM团队引入,旨在解决仅使用网络数据训练LLMs的挑战,而不是依赖需要大量人工干预的精心收集的文本集合。该数据集是为证明如果网络数据经过适当过滤和去重,其性能可以超越基于精选数据集(如 The Pile)训练的模型 [21]。
RefinedWeb 数据集包含约5万亿个标记,全部来自网络数据,主要来源于CommonCrawl数据集(一个公共的互联网爬取存储库)。其中,6000亿个标记在Hugging Face上公开可用(最后访问日期:2024年10月7日)。该数据集的巨大规模使其成为训练数十亿参数的大规模LLMs的重要资源,尤其是针对400亿到2000亿参数规模的模型 [21]。
这是一个基于英语的数据集,使用专有的 MacroData Refinement (MDR) 管道进行处理。该管道遵循严格的规则进行过滤和去重,工具如 trafilatura [116] 用于从原始HTML中提取内容,fastText [117] 用于语言识别。其他创建步骤包括过滤垃圾邮件、重复序列和其他低质量内容。最终输出通过自动化流程而非手动策划来匹配或超越精选数据集的质量 [21]。
RefinedWeb 数据集主要用于英语语言处理任务,但也可适应多种语言,用于零样本任务(如句子补全和问答)。其主要用途是预训练大规模语言模型,证明经过精心清洗的网络数据集可以超越精选数据集,这一点已被 Falcon 2、180B 和 40B 等模型验证。
尽管 RefinedWeb 数据集在NLP任务中表现出色,但它并未涉及代码相关任务。虽然比某些其他大型数据集小,但其严格的过滤使其在NLP任务中非常有效。然而,在本文中,我们决定将其与其他主要数据集(如 ROOTS 和 The Stack)一起介绍,目的是提出一种新的预训练方法:利用 RefinedWeb 进行NLP任务,同时结合专用数据集以增强代码理解和生成能力。
10.2 第二部分:用于微调和测试LLMs在软件漏洞检测与缓解中的专用数据集
在本节中,我们将介绍专门用于微调和测试LLMs以执行与软件漏洞检测和缓解相关任务的数据集。这些数据集相较于预训练阶段使用的基础数据集更加聚焦且任务特定。通过提供已知漏洞、弱点和攻击模式的详细信息,这些数据集使LLMs能够更深入地理解软件安全风险。在这些专用数据集上进行微调,可以使模型更准确地检测漏洞、预测潜在攻击并推荐有效的缓解策略。
这些数据集通常不仅用于微调,还用于测试LLMs在软件漏洞检测中的表现。在模型开发过程中,数据集通常被划分为训练集、验证集和测试集,每个部分都有明确的作用,以确保模型在未见数据上的性能良好且具有良好的泛化能力。
- 训练集:这是用于“训练”模型的数据,意味着模型学习输入(例如代码片段)和输出(例如识别出的漏洞)之间的模式和关系。模型通过调整其内部参数来最小化训练数据上的误差。
- 验证集:验证集在训练过程中用于调整超参数(如学习率或批量大小)并防止过拟合。它帮助评估模型在未见数据上的表现,从而允许在训练期间进行调整而无需使用测试集。
- 测试集:测试集完全独立于训练集和验证集。它用于在训练和验证阶段之后评估模型的最终性能。测试集提供了一个无偏的指标,用以衡量模型对新数据的泛化能力。这对于评估模型在现实场景中的有效性至关重要。
在软件漏洞检测的背景下,一种常见的做法是使用数据集的一部分进行微调,同时保留另一部分用于测试。这确保了模型在未见过的训练数据上进行评估,从而客观衡量其检测能力。通过这种方式划分数据集,研究人员可以确信模型的性能不会因过度拟合训练数据而产生偏差。将数据集划分为训练、验证和测试部分的方法有助于确保模型在检测不同软件代码库中的漏洞时既准确又可靠。
以下表格总结了用于微调的数据集的关键细节。每个数据集将在表格后详细介绍(表6)。
10.2.1 CVE 数据集
MITRE 是一家专注于网络安全研究的非营利组织,为安全社区提供了宝贵的资源。其中一个资源就是 CVE 数据集。CVE 数据集 是一个全面的漏洞数据集,自动从美国国家漏洞数据库(NVD)中的公共 CVE 记录收集和整理而来。
CVE 数据集包含有关公开披露的网络安全漏洞的信息。这些数据集对于研究人员、安全专业人员以及任何希望了解最新威胁的人来说都非常重要。截至2024年10月4日,共有 240,830 条 CVE 记录。它列出了软件系统中报告的漏洞。
CVE 数据集通常包括以下内容:
- CVE ID:由 MITRE 分配给特定网络安全漏洞的唯一代码。
- 描述:对漏洞的详细解释,包括受影响的软件、潜在影响以及如何被利用。
- CVSS 分数:一种评分系统(通用漏洞评分系统),根据漏洞的可利用性、影响范围等反映其严重性。
- 发布日期:漏洞被公开披露的日期。
- 参考文献:指向其他资源的链接,例如补丁、解决方案和漏洞利用代码。
- 受影响产品:可能受到该漏洞影响的软件程序或系统的列表。
为了帮助研究人员,我们整理了一份可以找到 CVE 数据集的资源列表:
- MITRE CVE:这是 CVE 数据的官方来源,提供多种格式的下载。(最后访问日期:2024年10月4日)
- 美国国家标准与技术研究院 (NIST)。(最后访问日期:2024年10月2日)
- 新的 CVE 官方网站。(最后访问日期:2024年10月4日)
- 新 CVE 网站下载页面:此页面提供截至2024年6月30日的旧版格式 CVE 列表下载,以及推荐的新 JSON 5.0 格式。(最后访问日期:2024年10月2日)
- CVE Details:该网站提供了一个可搜索的 CVE 数据库,包含额外信息,例如漏洞利用详情和供应商风险评分。(最后访问日期:2024年10月2日)
10.2.2 公共弱点枚举(CWE)数据集
CWE 是由 MITRE 维护的社区开发的软件和硬件弱点目录。它的设计目的是提供对可能导致系统漏洞的常见安全缺陷的标准化分类。CWE 数据集 的主要目标是帮助开发人员、安全专业人员和组织在软件开发、系统设计和安全评估过程中识别、理解和缓解这些弱点。CWE 条目提供了对这些弱点的全面描述,包括它们如何被利用以及如何避免或修复它们的指导 [119]。
CWE 框架 是一个分类软件弱点的系统,按类别组织,帮助用户从广泛的高层次问题到更具体的技术细节分析漏洞。例如,“安全功能”或“输入验证”,每个类别下还有更具体的条目。该数据集会定期更新,以包含新发现的弱点,确保其反映了软件和硬件漏洞的不断演变性质 [119]。
CWE 被开发人员广泛用于提高代码的安全性,被安全测试人员用于识别漏洞,并被组织用于合规性和风险管理目的。该数据集还在静态和动态分析工具等安全工具中发挥着关键作用,这些工具使用 CWE 映射来报告代码中的潜在问题。
要下载最新的 CWE 数据集,您可以访问 MITRE 官方 CWE 下载页面 [这里](最后访问日期:2024年10月7日)[119]。每个 CWE 条目包括以下详细信息:
- ID:弱点的唯一标识符。
- 名称:对弱点的简明描述。
- 描述:对弱点、其潜在后果以及如何被利用的更详细解释。
- 扩展描述:关于弱点的更多深入信息。
- 关系:与其他 CWE 和相关安全概念的连接。
- 层次结构:在结构化分类方案中组织的 CWE。
10.2.3 CAPEC 数据集
CAPEC 数据集 同样由 MITRE 提供,专注于对网络攻击模式进行分类。与 CWE 类似,CAPEC 提供了一种标准化的语言来理解攻击者的方法。CWE 条目以层级结构组织,展示了不同攻击模式之间的关系。这种组织方式帮助用户理解各种漏洞和攻击方法之间的联系 [91, 120]。
CAPEC 数据集 经过精心组织,以便在各种网络安全应用中使用。它采用了一种层级结构,根据攻击机制(如社会工程、基于网络的攻击和基于软件的攻击)以及攻击领域(如 Web 应用程序、移动设备和云服务)对攻击模式进行分类。这种组织结构使用户能够高效地浏览数据集并将其应用于特定场景。此外,攻击模式还通过其他标准进行分类,包括攻击的影响、前提条件和典型严重性。在使用方面,CAPEC 数据集 对于提升 LLMs 在多个领域的能力至关重要。它有助于识别和分类攻击模式,从而改进威胁情报和事件响应能力。该数据集还通过帮助 LLMs 理解和预测攻击向量支持安全培训,并通过识别软件中的潜在攻击向量协助漏洞分析。此外,CAPEC 在进行全面的安全审计中发挥了重要作用,确保对潜在威胁的全面覆盖。这种细致的组织和多方面的用途使 CAPEC 成为改进网络安全措施和防御的关键资源 [91, 120]。要下载最新的 CAPEC 数据集,您可以访问 MITRE 官方 CAPEC 下载页面(最后访问日期:2024年10月7日)。
10.2.4 CVEfixes
CVEfixes 数据集 最早由 Bhandari 等人 [121] 提出。这一综合性的漏洞数据集是研究漏洞的丰富资源,自动从美国 NVD 中公开可用的 CVE 记录中编译而成。该数据集通过将 CVE 相关信息链接到软件开发的不同层次(例如代码提交、单个文件、特定方法、存储库以及 CVE 本身),支持安全研究。这使得研究人员能够详细分析安全修复,并研究它们如何在多个抽象层次上解决漏洞。该数据集的初始版本涵盖了截至 2021 年 6 月 9 日发布的所有 CVE,包含来自 1,754 个开源项目的 5,495 个漏洞修复提交的信息,涵盖 180 种不同的 CWE 类型中的 5,365 个 CVE。此外,数据集还提供了 18,249 个文件和 50,322 个函数的修复前后源代码 [24, 34, 121]。
最新版本 v1.0.8 来自项目 GitHub 存储库(最后访问日期:2024年10月8日),包含了截至 2024 年 7 月 23 日发布的所有 CVE。在此期间,NVD 中引用的所有具有公开可访问 Git 存储库的开源项目均被收集并整合到数据集中。该漏洞数据集以关系数据库的形式组织,涵盖 4,249 个开源项目的 12,107 个漏洞修复提交,代表了 272 种不同 CWE 类别中的 11,873 个 CVE。此外,数据集还提供了影响 51,342 个文件和 138,974 个函数的修改前后的源代码快照。
利用 LLMs 进行软件漏洞任务的研究人员可以从该数据集中受益,通过其结构化、相互关联的数据训练模型以应对现实世界的漏洞场景。该数据集还为微调旨在改进开源项目安全实践的模型提供了良好的基础。然而,研究人员应注意潜在挑战,例如噪声数据或需要在不同抽象层次(例如文件、方法或提交级别)上预处理信息。
10.2.5 DiverseVul
DiverseVul 数据集 最早由 Chen 等人 [67] 提出,旨在通过 DL 技术检测软件漏洞。DiverseVul 包含 18,945 个漏洞函数,涵盖 155 种 CWE 和 330,492 个非漏洞函数,来源于 7,514 次提交。该数据集覆盖了比任何先前发布的数据集多 295 个项目的范围,使其成为 C/C++ 漏洞领域最多样化的资源之一。DiverseVul 包含来自各种项目的现实数据,显著扩展了漏洞和非漏洞函数的数量和多样性,相较于之前的 CVEFixes 等数据集有了显著提升。
利用 DiverseVul,[67] 的研究调查了多种 DL 架构在漏洞检测中的有效性。它探索了来自四种模型家族的 11 种不同 DL 架构:GNN、RoBERTa、GPT-2 和 T5。研究结果表明,训练数据的多样性和数量增加有助于提升漏洞检测能力,特别是对于 LLMs [67]。您可以通过以下链接下载 DiverseVul 数据集(最后访问日期:2024年10月10日)。
10.2.6 软件保障参考数据集(SARD)
SARD 数据集 由 NIST 维护,提供了一个全面的测试用例集合,旨在帮助研究人员、工具开发者和最终用户评估软件保障工具。这些测试用例涵盖了软件生命周期的各个阶段,包括设计、源代码和二进制文件,并包含已知的安全漏洞及其对应的修复方案。数据集的样本来源包括合成数据(专门用于测试)、真实生产软件和学术研究。其主要目标是支持软件安全工具的评估,并促进新方法的开发以检测和缓解漏洞 [122]。
SARD 数据集 包含约 500,000 个测试用例,是最大的公开可用软件漏洞测试资源之一。它涵盖了 6 种编程语言,包括 C、C++、Java、PHP 和 C#。用户可以搜索、查看和下载单个测试用例或整个测试套件,使其成为软件安全领域研究人员和开发人员的重要工具。SARD 不断发展,持续改进以提升可用性和搜索功能,使用户能够更高效地访问和分析测试用例 [122]。
SARD 因同时包含安全漏洞和非漏洞替代方案而显得尤为吸引人。这一特性使得 LLM 能够有效区分这些不同的类别。随后,可以通过实施预处理阶段来消除可能引起模型过拟合的任何不良伪影。SARD 数据集被广泛用于许多实验中,包括 [13, 15, 67, 74, 75, 87]。
下载 SARD 数据集的最佳和最官方来源是 NIST。您可以直接从其官方网站访问和下载该数据集(最后访问日期:2024 年 10 月 10 日)。
10.2.7 基于语义的漏洞候选(SeVC)
SeVC 数据集包含来自 NVD 的 1,591 个 C/C++ 开源程序,以及来自 SARD 的 14,000 个开源程序。它总共包含 420,627 个源代码元素实例,称为 SeVCs。其中,56,395 个被分类为漏洞,而 364,232 个被认为是非漏洞 [13, 74, 123]。该数据集聚焦于四种主要类型的源代码模式,这些模式可能影响安全性:
- 库/API 函数调用:使用外部库或 API。
- 数组使用:涉及数组的操作。
- 指针使用:代码中对指针的处理。
- 算术表达式:代码中的数学运算。
SeVC 数据集在 SySeVR 项目 GitHub 仓库中公开可用(最后访问日期:2024 年 10 月 6 日)。
研究人员可以利用 SeVC 数据集,通过提供丰富的真实世界漏洞和修复示例,增强 LLM 在软件漏洞检测和缓解方面的能力。SeVC 数据集包含标记为漏洞和非漏洞的代码段,使 LLM 能够理解与漏洞相关的语义代码模式。
10.2.8 Devign
Devign 数据集最初在 [124] 中提出,是一个用于识别软件漏洞的真实世界数据集。Devign 数据集旨在通过深度学习(DL),特别是使用图神经网络(GNN),支持漏洞识别。它基于四个大规模开源 C 项目(Linux 内核、QEMU、Wireshark 和 FFmpeg)的手动标注数据集构建,包含 58,965 个代码片段,目标是增强对代码语义的理解。该数据集聚焦于漏洞函数和非漏洞函数,这些函数从漏洞修复提交和非漏洞修复提交中提取,提供了真实世界的复杂性和多样性,而非合成或人工代码。
为了确保质量,一个安全专家团队通过两阶段流程手动标注了数据集,包括筛选与安全相关的提交,并从源代码中提取漏洞函数 [124]。
Devign 使用一种高级方法,通过基于图的表示形式检测代码中的漏洞。它结合了以下几个关键要素:
- 抽象语法树(ASTs):捕获代码的结构。
- 控制流图(CFGs):展示代码不同部分的执行顺序。
- 数据流图(DFGs):追踪数据如何在代码中流动。
- 自然代码序列(NCSs):以开发人员编写的自然顺序表示代码。
通过整合这些不同的视角,Devign 创建了更全面的代码分析,以识别潜在漏洞。这些表示形式捕捉了代码的不同语义和结构特征,使 GNN 模型能够识别与漏洞相关的各种模式。Devign 数据集支持在函数级别进行详细分析,为机器学习模型理解和学习代码中的复杂关系提供了绝佳机会。通过关注这种级别的细节,研究人员可以训练模型识别对识别漏洞至关重要的模式和联系。该数据集因其全面的手动标注而脱颖而出,这为其增加了显著的深度和可靠性。这些特性使 Devign 成为创建精密漏洞检测系统的重要资源 [124]。
Devign 已经过充分测试,证明其在检测漏洞方面比旧方法更有效。它的准确率提高了多达 10.51%,F1 分数提升了 8.68%,突显了其基于图分析的强大能力。此外,Devign 在识别现实世界项目中新发现的漏洞方面表现出高度可靠性,展示了其在提升软件安全性方面的实际价值 [124]。
10.2.9 HumanEval
HumanEval 数据集由 Chen 等人在 [32] 中提出,作为他们评估基于代码训练的大语言模型工作的一部分。该数据集提供了一个专门设计的基准,用于衡量 LLM 在代码生成任务中的能力。HumanEval 包含 164 个 Python 编程问题,每个问题均附有函数签名、任务的自然语言描述以及用于验证生成解决方案正确性的单元测试。这些单元测试确保生成的代码按预期运行并满足问题要求。
该数据集的主要目的是评估 LLM 生成代码的功能正确性,使用如 Pass@k 等指标进行衡量,该指标评估正确的解决方案是否出现在前 k 个生成输出中。HumanEval 专注于 Python,使其成为针对该语言评估 LLM 的定向基准。
该数据集是研究人员开发或微调 LLM 以执行与软件漏洞检测和缓解相关任务的重要工具。尽管它并未明确涉及漏洞,但其对生成正确且功能完整的代码的关注对于生产安全的软件解决方案至关重要。研究人员通过利用 HumanEval 的明确定义的问题和强大的评估指标,可以对 LLM 性能进行详细分析。
HumanEval 数据集在 humaneval GitHub 仓库中公开可用(最后访问日期:2024 年 12 月 11 日)。该数据集也可通过 Hugging Face 和 TensorFlow 获取。
10.2.10 Big-Vul
Big-Vul 数据集 [125] 是一个全面的 C/C++ 代码漏洞集合,来自 GitHub 项目和 CVE 数据库。它通过对 CVE 数据库中的详细信息进行提取创建,包括漏洞 ID、严重性评分和摘要。覆盖了 2002 至 2019 年间报告的漏洞,数据集中每个条目包含 21 个不同特征。包括以下特征:
- 访问复杂性:利用漏洞的难度。
- 所需认证:是否需要认证才能利用漏洞。
- 可用性影响:如果被利用,对系统可用性的影响。
- 提交 ID:代码仓库中的提交 ID,表示一个小版本。
- 提交信息:开发者关于代码更改的提交信息。
- 保密性影响:对敏感信息的风险。
- CWE ID:常见弱点枚举 ID。
- CVE ID:常见漏洞和暴露 ID。
- CVE 页面:指向更多漏洞信息的 URL。
- CVE 摘要:CVE 摘要信息。
- CVSS 评分:漏洞的严重程度。
- 文件更改:更新代码和修复的详细信息。
- 完整性影响:数据篡改或破坏的风险。
- 修复后的小版本:修复后的小版本 ID。
- 修复前的小版本:修复前的小版本 ID。
- 编程语言:项目使用的编程语言。
- 项目名称。
- CVE 发布日期。
- 参考链接:CVE 页面中的参考链接。
- CVE 更新日期。
- 漏洞分类:漏洞类型。
这些漏洞随后与 GitHub 仓库中的相应代码更改相关联。每个 Big-Vul 条目将一个 CVE 与其特定的 GitHub 代码提交配对,从而在漏洞及其修复之间建立了清晰的关联。总计,Big-Vul 包含来自 348 个开源项目的 3,754 个代码漏洞,涵盖 91 种不同的漏洞类型。数据集以 CSV 格式存储,代码更改与描述性的 CVE 信息相关联,使其在漏洞检测和修复研究中非常有用 [125]。
与其他漏洞数据集相比,Big-Vul 因其全面性而脱颖而出。它不仅提供了漏洞类型和代码修复的详细信息,还包括广泛特征,例如安全评分和代码修改。相比其他数据集,Big-Vul 包含更多的漏洞和详细信息,共有 4,432 个代码提交、8,143 个修改文件和 11,823 个漏洞函数。这使其成为研究人员分析漏洞特征、改进检测机制以及研究各级别漏洞相关代码更改的重要资源 [60, 125]。
要访问 Big-Vul 数据集,您可以访问该项目的官方 GitHub 仓库(最后访问日期:2024 年 10 月 10 日)。
10.2.11 PrimeVul
PrimeVul 是一个新引入的数据集,旨在解决现有数据集在代码漏洞检测中的局限性。它采用了改进的数据收集、标注和评估技术。与之前存在数据重复和标签准确性低等问题的数据集不同,PrimeVul 实施了严格的去重流程,以消除重复或相似的数据样本。该数据集整合了来自 BigVul、CrossVul 和 CVEFixes 等先前数据集的安全相关提交和函数,同时排除了 Devign/CodeXGLUE 等被发现包含无关安全数据的来源。PrimeVul 对仅在格式上不同的代码副本和函数进行去重,以确保数据的清洁性和唯一性 [126]。
PrimeVul 使用两种创新方法进行标注:一种方法是将安全修复中唯一被修改的函数标记为漏洞;另一种方法是将 NVD 中的漏洞描述与安全相关的代码更改相匹配。这一过程生成了一个高质量的大规模数据集,包含 755 个项目和 140 种 CWE 类型中的 6,968 个漏洞函数和 228,800 个非漏洞函数,其质量可与手动验证的数据集(如 SVEN)相媲美 [126]。
PrimeVul 还改进了漏洞检测模型的评估方法。它使用时间分割(temporal splits,即将训练数据与未来数据分离,以避免在真实场景中模型接触到未出现的信息)来防止数据泄露(data leakage,即在训练过程中无意使用测试集信息,可能导致过于乐观的结果)。此外,PrimeVul 引入了漏洞检测评分(VD-S),用于在控制假阳性(将非漏洞代码错误地标记为漏洞)的同时衡量模型的准确性。PrimeVul 还提供成对评估(pair-wise evaluation,即测试模型区分漏洞代码及其修复版本的能力),以帮助模型更好地识别漏洞代码和其修复版本之间的差异,从而实现更真实的性能评估 [126]。 PrimeVul 数据集在 PrimeVul 项目 GitHub 仓库中公开可用(最后访问日期:2024 年 10 月 10 日)。
10.2.12 LineVul
LineVul 是一个旨在通过专注于行级细粒度预测来解决漏洞检测局限性的数据集(这意味着它能够识别特定代码行中的漏洞,而不仅限于函数或一般代码块级别),特别是针对 C 和 C++ 代码。该数据集包含 188,636 个函数,涵盖超过 91 种 CWE 类型,并提供了行级的真实标签(准确标注哪些具体代码行存在漏洞)。这种细粒度预测有助于精确定位漏洞的具体位置,使开发人员更容易修复问题。 其关键特点之一是,仅有 5.7% 的函数被标记为漏洞,这为测试面向漏洞检测的机器学习模型提供了现实且具有挑战性的环境 [127]。 LineVul 数据集及相关资源可通过项目的官方 GitHub 仓库获取(最后访问日期:2024 年 10 月 10 日)。
RQ8 回答:
用于训练、微调或测试 LLM 以检测软件漏洞的数据集包括基础数据集和专用数据集。基础数据集如 CodeSearchNet、The Pile、GitHub Code、ROOTS、RefinedWeb 和 The Stack 被用于预训练 LLM,帮助模型学习各种编程语言和领域的通用编码模式。这些数据集为模型理解代码结构和语义提供了广泛的语言和编程知识。
对于专门针对漏洞检测的 LLM 微调和测试,专用数据集如 CVE、CWE、CAPEC、CVEFixes、DiverseVul、SARD、SeVC、Devign、Big-Vul、PrimeVul 和 LineVul 至关重要。这些数据集聚焦于软件漏洞、弱点和安全风险的详细信息,使模型能够在代码的函数和行级别上专门识别、预测和缓解漏洞。
11 RQ9. 用于评估 LLM 在应对软件漏洞方面的指标是什么?
评估指标对于衡量 LLM 在软件漏洞和网络安全应用中的有效性和成功至关重要。这些指标为量化模型在与软件漏洞和网络安全威胁相关任务中的表现提供了框架,例如漏洞检测、威胁预测和自动修复。鉴于这些任务的多样性,采用针对特定问题类型的多种评估指标是一种常见做法。
在本节中,我们将对用于软件漏洞检测和缓解的 LLM 的评估指标进行分类,并将其分为三类,分别对应其解决的任务类型(分类、推荐和生成)。
对于每个指标,我们将提供简短介绍,包括其重要性和应用。此外,我们还将概述计算每个指标的公式或步骤,以确保清晰和精确。必要时,我们将提供简明示例,以便读者更好地理解这些指标。
11.1 分类任务
对于涉及分类的任务,例如识别漏洞类型或预测潜在威胁,常用的指标包括 F1 分数(F-measure)、精确率(Precision)和召回率(Recall)[1, 11, 16, 67, 73, 74, 80, 123, 128]。
11.1.1 F1 分数
F1 分数,也称为 F 度量 [128],是一种通过综合考虑精确率(precision)和召回率(recall)来评估二分类模型性能的指标。精确率是指模型预测为正类的结果中真正类结果的比例,而召回率是指实际正类结果中被正确识别为正类的比例。F1 分数是精确率和召回率的调和平均值,提供了一个衡量模型准确性的单一指标。在软件漏洞检测与缓解的背景下,F1 分数尤为重要,因为它平衡了精确率和召回率之间的权衡。高精确率意味着模型能够以较少的假阳性准确识别漏洞,而高召回率意味着模型能以较少的假阴性检测到大多数实际存在的漏洞。高 F1 分数表明模型在这两方面表现良好,这对于有效识别和缓解软件系统中的漏洞至关重要 [128]。
F 1 − s c o r e = 2 × P r e c i s i o n × R e c a l l P r e c i s i o n + R e c a l l F1-score = \frac{2 \times Precision \times Recall}{Precision + Recall} F1−score=Precision+Recall2×Precision×Recall
F1 分数的局限性
- 对不平衡数据敏感:在漏洞检测中常见的不平衡数据集上表现不佳。
- 阈值依赖性:需要为二分类设定一个阈值。
- 单标签聚焦:不适用于多标签分类任务。
11.1.2 精确率
精确率是真正类(正确预测的漏洞)与所有正类预测(所有预测的漏洞)的比例。
P r e c i s i o n = T r u e P o s i t i v e s ( T P ) T r u e P o s i t i v e s ( T P ) + F a l s e P o s i t i v e s ( F P ) Precision = \frac{True\ Positives (TP)}{True\ Positives (TP) + False\ Positives (FP)} Precision=True Positives(TP)+False Positives(FP)True Positives(TP)
精确率的局限性
- 忽略假阴性:假阴性在安全场景中至关重要。
- 受不平衡数据影响:在正类样本较少的不平衡数据集中受影响较大。
- 范围有限:仅关注正类预测,无法衡量模型的整体有效性。
11.1.3 召回率
召回率是真正类与所有实际正类(所有实际漏洞)的比例。
R e c a l l = T r u e P o s i t i v e s ( T P ) T r u e P o s i t i v e s ( T P ) + F a l s e N e g a t i v e s ( F N ) Recall = \frac{True\ Positives (TP)}{True\ Positives (TP) + False\ Negatives (FN)} Recall=True Positives(TP)+False Negatives(FN)True Positives(TP)
召回率的局限性
- 忽视假阳性:导致特异性较低。
- 鼓励模型预测更多正类:降低精确率。
- 在准确性比覆盖率更重要的场景中可能误导。
- 未提供输出可靠性或正确性的度量。
11.1.4 真/假阳性率 与 真/假阴性率
在分类或检测任务(例如使用 LLM 进行软件漏洞识别)中,真正类(TP)、假正类(FP)、真阴类(TN)和假阴类(FN)是评估模型性能的关键组成部分。
- 真正类(TP):模型正确识别正类的情况(例如,正确检测到的漏洞)。
- 假正类(FP):模型错误地识别为正类的情况(例如,将安全代码误分类为漏洞)。
- 真阴类(TN):模型正确识别负类的情况(例如,正确识别安全代码为非漏洞)。
- 假阴类(FN):模型未能识别正类的情况(例如,漏掉的实际漏洞)。### 11.1.5 准确率
11.1.5 准确率
在分类任务中,准确率表示正确分类的实例(包括正类和负类)占总实例的比例。
A c c u r a c y ( % ) = number of correctly classified instances total number of instances × 100 = T P + T N T P + T N + F P + F N × 100 Accuracy(\%) = \frac{\text{number of correctly classified instances}}{\text{total number of instances}} \times 100 = \frac{TP + TN}{TP + TN + FP + FN} \times 100 Accuracy(%)=total number of instancesnumber of correctly classified instances×100=TP+TN+FP+FNTP+TN×100
其中:
- TP:真正类(正确识别的漏洞)。
- TN:真阴类(正确识别的非漏洞)。
- FP:假正类(错误分类为漏洞的非漏洞)。
- FN:假阴类(错误分类为非漏洞的漏洞)。
准确率的局限性
- 对不平衡数据集无效:掩盖了关键类别上的较差表现。
- 不区分假正类和假阴类。
- 对所有错误一视同仁,这在安全场景中的关键错误上并不理想。
- 在类别分布差异较大的情况下可能具有误导性。
11.1.6 AUC-ROC
接收者操作特性曲线下的面积(AUC-ROC)是评估分类模型性能的广泛使用的指标。ROC 曲线是以不同阈值设置下真正类率(TPR)和假正类率(FPR)之间的权衡为依据的图形化表示。该曲线下方的面积(AUC)提供了一个总结分类器性能的单一标量值。AUC-ROC 评估了模型在不同分类阈值下区分正类和负类的能力。更高的 AUC-ROC 值表明整体性能更好 [129]。
AUC-ROC 特别适用于评估以下内容:
- 二分类任务,例如判断一段代码是否包含漏洞。
- 多分类任务,例如将代码分类为不同的漏洞类型或软件组件。
- 不平衡数据集,在这种情况下,评估模型在不同阈值下的表现非常重要。
ROC 曲线是真正类率(TPR)与假正类率(FPR)的图形化表示,其公式分别为:
T P R = T P T P + F N , F P R = F P F P + T N TPR = \frac{TP}{TP + FN}, \quad FPR = \frac{FP}{FP + TN} TPR=TP+FNTP,FPR=FP+TNFP
AUC 是 ROC 曲线下的面积,其值范围从 0 到 1,其中:
- 1.0:完美区分(理想模型)。
- 0.5:随机猜测(无区分能力)。
- < 0.5:比随机猜测更差。
ROC 曲线和 AUC 面积的示例可见图 7。
计算 AUC-ROC 的步骤:
- 绘制每个阈值下的 (FPR, TPR) 点。
- 使用梯形法则计算面积:
梯形法则通过求解相邻点之间形成的梯形面积之和来近似曲线下面积。
A
U
C
=
∑
i
=
1
n
−
1
(
F
P
R
i
+
1
−
F
P
R
i
)
×
T
P
R
i
+
T
P
R
i
+
1
2
AUC = \sum_{i=1}^{n-1} (FPR_{i+1} - FPR_i) \times \frac{TPR_i + TPR_{i+1}}{2}
AUC=i=1∑n−1(FPRi+1−FPRi)×2TPRi+TPRi+1
其中:
- n 是 ROC 曲线上的点数。
- FPR_i 和 TPR_i 分别是第 i 个阈值下的假正类率和真正类率。
例如:对于两点 (FPR1, TPR1) 和 (FPR2, TPR2),梯形面积为:
A
U
C
=
(
F
P
R
2
−
F
P
R
1
)
×
(
T
P
R
1
+
T
P
R
2
)
2
AUC = (FPR_2 - FPR_1) \times \frac{(TPR_1 + TPR_2)}{2}
AUC=(FPR2−FPR1)×2(TPR1+TPR2)
AUC-ROC 的优点:
- 阈值独立性:评估模型在所有分类阈值下的表现。
- 对类别不平衡的鲁棒性:相较于准确率等指标,对不平衡数据集的敏感性较低。
- 直观解释:更高的 AUC-ROC 值表明模型在区分类别方面表现更好。
AUC-ROC 的局限性:
- 未提供特定阈值下的性能信息。
- 在严重不平衡的数据集中可能不理想,其他指标(如精确率、召回率)可能更具洞察力。
- 假设假正类率和真正类率的重要性一致。
11.2 推荐任务
在软件漏洞检测与缓解领域,推荐任务是指向开发人员或安全团队建议潜在漏洞、修复方法或缓解策略的过程。其目标是帮助他们识别并优先处理漏洞,并提供解决这些漏洞的指导。
此领域的一些常见推荐任务包括:
- 漏洞预测:预测某段代码是否可能包含漏洞。
- 漏洞排名:按严重性或可能性对潜在漏洞进行排序。
- 修复建议:为已识别的漏洞提供建议的修复或补丁。
- 缓解建议:推荐策略或技术以减轻漏洞的影响。
MRR、Precision@k、Recall@k、F1-score@k 和准确率是常用于评估推荐系统性能和排名结果质量的指标,包括推荐代码片段或补全的系统。这些指标有助于评估模型在其输出的前 k 项中优先考虑相关结果的准确性 [16, 33, 110]。在评估指标中,@k 表示法用于指定指标在某个特定截断点处进行评估,通常是排名列表中的前 k 项。换句话说,@k 表示“在 k 处”或“直到 k”,其中 k 是一个正整数。它表示仅考虑列表中的前 k 项,而不是整个列表(见图 8)。
11.2.1 平均倒数排名 (MRR)
MRR 是信息检索和自然语言处理中常用的评估排名系统性能的指标。它也是与代码补全相关的推荐系统的常用指标。MRR 通过确定模型为给定查询排名最相关结果的效果(第一个相关推荐在建议列表中出现的速度)来衡量模型的有效性。MRR 在评估 LLMs 在识别和优先处理代码中潜在漏洞方面的有效性时尤为有用 [130]。
MRR 被计算为一组查询中第一个相关项目的倒数排名的平均值:
M
R
R
=
1
N
∑
i
=
1
N
1
rank
i
MRR = \frac{1}{N} \sum_{i=1}^{N} \frac{1}{\text{rank}_i}
MRR=N1i=1∑Nranki1
其中:
- N 是查询总数。
- rank_i 是第 i 个查询中第一个相关项目的排名位置。
示例计算
假设我们有 3 个查询,第一个相关结果的排名如下:
- 查询 1:相关结果位于排名 1。
- 查询 2:相关结果位于排名 3。
- 查询 3:无相关结果(倒数排名为 0)。
MRR 的计算为:
M
R
R
=
1
3
(
1
1
+
1
3
+
0
)
=
1
3
(
1
+
0.333
+
0
)
=
0.444
MRR = \frac{1}{3} \left( \frac{1}{1} + \frac{1}{3} + 0 \right) = \frac{1}{3} (1 + 0.333 + 0) = 0.444
MRR=31(11+31+0)=31(1+0.333+0)=0.444
MRR 得分为 0.444,表示模型在排名相关结果方面的平均有效性。
11.2.2 F1-score@k
F1-score@k 在 Precision@k 和 Recall@k 之间提供了平衡,突出了精确率和前 k 项中相关结果覆盖范围之间的权衡。
F 1 − score @ k = 2 × Precision @ k × Recall @ k Precision @ k + Recall @ k F1-\text{score}@k = \frac{2 \times \text{Precision}@k \times \text{Recall}@k}{\text{Precision}@k + \text{Recall}@k} F1−score@k=Precision@k+Recall@k2×Precision@k×Recall@k
11.2.3 Precision@k
Precision@k 评估前 k 项推荐中相关结果的比例,强调模型避免假正类的能力。
Precision @ k = ∣ Relevant Results in Top-k ∣ k \text{Precision}@k = \frac{| \text{Relevant Results in Top-k} |}{k} Precision@k=k∣Relevant Results in Top-k∣
其中:
- |Relevant Results in Top-k| 是模型推荐的前 k 项中相关结果的数量。
- k 是考虑的顶部推荐子集的大小。
11.2.4 Recall@k
Recall@k 衡量前 k 项推荐中捕获的相关结果数量。较高的值意味着模型检索到了更大比例的所有可能相关结果。
Recall @ k = ∣ Relevant Results in Top-k ∣ ∣ Total Relevant Results ∣ \text{Recall}@k = \frac{| \text{Relevant Results in Top-k} |}{| \text{Total Relevant Results} |} Recall@k=∣Total Relevant Results∣∣Relevant Results in Top-k∣
其中:
- |Total Relevant Results| 是查询中所有相关结果的总数。
11.2.5 准确率
在推荐任务中,准确率用于衡量正确推荐的项目(例如,安全编码实践、漏洞缓解策略)占总推荐的比例。
Accuracy (%)
=
Number of Relevant or Correct Recommendations
Total Number of Recommendations
×
100
\text{Accuracy (\%)} = \frac{\text{Number of Relevant or Correct Recommendations}}{\text{Total Number of Recommendations}} \times 100
Accuracy (%)=Total Number of RecommendationsNumber of Relevant or Correct Recommendations×100
11.2.6 Accuracy@k
Accuracy@k 是一种用于评估模型在考虑前 k 项推荐或预测任务中性能的指标。它衡量正确项目被包含在模型生成的前 k 项推荐或预测中的实例比例。
A
c
c
u
r
a
c
y
@
k
(
%
)
=
Number of Instances with Correct Item in Top-k Recommendations
Total Number of Instances
×
100
Accuracy@k (\%) = \frac{\text{Number of Instances with Correct Item in Top-k Recommendations}}{\text{Total Number of Instances}} \times 100
Accuracy@k(%)=Total Number of InstancesNumber of Instances with Correct Item in Top-k Recommendations×100
计算 Accuracy@k 的步骤:
- 定义 k:确定 k 的值,即需要考虑的前 k 项推荐或预测的数量。例如,如果评估前 3 项推荐,则 k = 3 k = 3 k=3。
- 识别正确项目:对于每个实例(例如,代码片段或漏洞),确定正确项目(例如,安全代码建议或缓解策略)是否包含在前 k 项推荐中。
- 统计正确实例:统计正确项目被包含在前 k 项推荐中的实例数量。
- 计算 Accuracy@k:使用公式计算准确率百分比。
11.3 生成任务
生成任务涉及使用 LLMs 根据给定输入生成新内容,例如代码片段、补丁或解释。在软件漏洞检测与缓解的背景下,生成任务可以包括以下内容:
代码生成:
- 漏洞代码识别:生成突出潜在漏洞的代码片段。
- 安全代码建议:为漏洞代码片段生成安全的替代方案。
- 自动修补:为已识别的漏洞生成补丁或修复方案。
解释生成:
- 漏洞解释:生成自然语言解释,说明特定代码片段为何存在漏洞。
- 缓解策略:生成如何缓解已识别漏洞的建议。
- 提供安全编码指南或模板:例如,建议安全的 API 使用模式。
文档生成:
- 安全指南:生成包含安全最佳实践和指南的文档。
- 代码注释:生成解释代码片段安全影响的注释。
评估 LLMs 在此领域生成任务的性能需要衡量输出的相关性、准确性和质量的指标。常用的指标包括 BLEU 及其变体(如 BLEU-4、CodeBLEU 和 BLEU-DC)以及 Pass@k。这些指标广泛用于代码到代码翻译模型和代码生成评估,比较生成的代码片段与参考解决方案的质量和准确性。此外,其他指标如 ROUGE/ROUGE-L、METEOR、EM(完全匹配)和 ES(编辑相似度)在特定研究中被用来评估生成代码或自然语言代码描述的质量 [16, 32, 131, 132]。
11.3.1 代码覆盖率
代码覆盖率 [133] 主要用于评估软件测试任务。它衡量程序源代码的行、分支或路径在测试期间被执行的程度。虽然它被用于评估生成测试的全面性或生成代码的执行情况,但它通常不与其他生成任务(如文本/代码生成任务中的 BLEU 或 CodeBLEU 指标)归为一类。因此,其使用可能更为有限。它主要用于评估与代码合成和代码补全相关的生成任务,确保生成的代码有效、功能正常且经过充分测试。在软件漏洞检测和缓解的背景下,它可以用于评估自动化补丁生成或测试用例生成任务的全面性。
代码覆盖率的类型
有多种代码覆盖率指标,每种关注代码的不同方面:
- 语句覆盖率:衡量测试套件执行的代码语句的百分比。
- 函数覆盖率:衡量测试套件调用的代码函数的百分比。
- 行覆盖率:衡量至少执行一次的可执行代码行的百分比。
- 表示代码库中有多少部分被直接测试。
- 分支覆盖率:衡量代码中分支(例如“if”或“else”路径)被执行的百分比。
- 确保代码逻辑分支得到充分测试。
- 路径覆盖率:衡量测试套件执行的代码中所有可能路径的百分比。
- 提供最全面的评估,但计算成本较高。
计算代码覆盖率的一般公式为:
Code Coverage (%) = ( Number of Covered Items Total Number of Items ) × 100 \text{Code Coverage (\%)} = \left( \frac{\text{Number of Covered Items}}{\text{Total Number of Items}} \right) \times 100 Code Coverage (%)=(Total Number of ItemsNumber of Covered Items)×100
其中,“Items”可以指代执行的语句、分支、调用的函数、执行的行或执行的路径,具体取决于所测量的覆盖率类型。
代码覆盖率的局限性
代码覆盖率有几个需要注意的局限性。首先,高代码覆盖率并不能保证没有缺陷;即使进行了广泛的测试,缺陷仍可能存在。其次,代码覆盖率指标仅关注执行的代码,这意味着它们无法评估代码在各种条件下的行为是否正确。最后,对于复杂的应用程序,实现完全路径覆盖在计算上可能是不可行的,这使得彻底测试变得昂贵且资源密集。这些局限性突显了需要超越代码覆盖率指标的补充测试策略。
11.3.2 准确率
在生成任务中,准确率衡量正确生成的输出(如补丁、漏洞描述或攻击场景)占总生成输出的比例。这通常被评估为完全匹配准确率。准确率的计算公式为正确生成的输出与总生成输出的比值。
A c c u r a c y ( % ) = Number of Correctly Generated Outputs Total Number of Generated Outputs × 100 Accuracy(\%) = \frac{\text{Number of Correctly Generated Outputs}}{\text{Total Number of Generated Outputs}} \times 100 Accuracy(%)=Total Number of Generated OutputsNumber of Correctly Generated Outputs×100
11.3.3 BLEU、BLEU-4、BLEU-DC
BLEU(Bilingual Evaluation Understudy)分数 [134] 是一种用于评估模型生成文本质量的指标,与参考文本进行比较。它广泛应用于机器翻译和自然语言生成任务。在软件漏洞检测与缓解的背景下,BLEU 分数可用于评估 LLM 生成或修改以修复漏洞的代码质量。
BLEU 的公式为:
B L E U = B P ⋅ exp ( ∑ n = 1 N w n log p n ) BLEU = BP \cdot \exp \left( \sum_{n=1}^{N} w_n \log p_n \right) BLEU=BP⋅exp(n=1∑Nwnlogpn)
其中:
- BP 是简洁性惩罚(Brevity Penalty),用于惩罚过于简短的翻译。
- p_n 是 n 元组(n-grams)的精确率(n 元组是连续单词或标记的序列)。
- w_n 是 n 元组的权重,允许对不同大小的 n 元组分配不同的重要性。
- N 是考虑的最大 n 元组阶数。
简洁性惩罚(BP)
BP 是 BLEU 分数的一个组成部分,用于惩罚相对于参考翻译而言过短的翻译。这一点很重要,因为模型可能通过生成非常短的输出来获得高精确率,但这些输出可能没有意义或不完整。简洁性惩罚确保生成的文本具有合理的长度。计算 BP 的步骤如下:
- 定义长度:
- 设 c c c 为候选翻译(生成文本)的长度。
- 设 r r r 为参考翻译(真实文本)的长度。
- 计算简洁性惩罚:
- 如果 c > r c > r c>r,则 B P = 1 BP = 1 BP=1(无惩罚)。
- 如果 c < r c < r c<r,则 B P = exp ( 1 − r c ) BP = \exp \left( 1 - \frac{r}{c} \right) BP=exp(1−cr)。
n 元组 是句子或代码中连续 n n n 个单词或标记的序列。例如:对于句子 “The function is defined”,其 2 元组(bigrams)为:
- “The function”
- “function is”
- “is defined”
对于同一句子,其 4 元组(4-g)为整个短语:“The function is defined”。
BLEU-4
BLEU-4 是 BLEU 分数的一种特定变体,考虑了高达 4 元组的内容。更高阶的 n 元组(如 4 元组)能够捕捉更多的上下文和结构,因此像 BLEU-4 这样的指标在评估代码片段等任务中特别有价值,因为在这些任务中理解多个标记之间的关系至关重要。在 BLEU-4 中,
N
=
4
N = 4
N=4,且
n
n
n 的范围为 1 到 4。因此,BLEU-4 的计算公式为:
B L E U − 4 = B P ⋅ exp ( ∑ n = 1 4 w n log p n ) BLEU-4 = BP \cdot \exp \left( \sum_{n=1}^{4} w_n \log p_n \right) BLEU−4=BP⋅exp(n=1∑4wnlogpn)
其中:
- BP 是简洁性惩罚。
- p n p_n pn 是 n n n 元组的精确率( n = 1 n = 1 n=1 到 4)。
- w n w_n wn 是 n n n 元组的权重(通常在 BLEU-4 中 w n = 1 / 4 w_n = 1/4 wn=1/4)。
BLEU-DC
BLEU-DC 是 BLEU(Bilingual Evaluation Understudy)分数的一种变体,广泛用于评估文本生成的质量。BLEU-DC 引入了折扣累积增益(Discounted Cumulative Gains, DCG)的概念,以考虑生成文本不同部分的重要性差异。这在软件漏洞检测与缓解中尤为重要,因为代码的某些部分(例如安全性关键部分)比其他部分更为重要。
BLEU-DC 的公式为:
B L E U − D C = B P ⋅ exp ( ∑ n = 1 N w n log ( D C G n I D C G n ) ) BLEU-DC = BP \cdot \exp \left( \sum_{n=1}^{N} w_n \log \left( \frac{DCG_n}{IDCG_n} \right) \right) BLEU−DC=BP⋅exp(n=1∑Nwnlog(IDCGnDCGn))
其中:
- BP 是简洁性惩罚。
- D C G n DCG_n DCGn 是 n n n 元组的折扣累积增益。
- I D C G n IDCG_n IDCGn 是 n n n 元组的理想折扣累积增益。
- w n w_n wn 是 n n n 元组的权重。
折扣累积增益(DCG)
DCG 是一种衡量序列相关性的指标,同时赋予更相关的部分更高的权重,尤其是出现在序列较前的部分。对于
n
n
n 元组,其计算公式为:
D C G n = ∑ i = 1 P RelevanceScore i log 2 ( i + 1 ) DCG_n = \sum_{i=1}^{P} \frac{\text{RelevanceScore}_i}{\log_2(i + 1)} DCGn=i=1∑Plog2(i+1)RelevanceScorei
其中:
- P:考虑的 n n n 元组总数。
- RelevanceScore_i:第 i i i 个 n n n 元组与参考文本匹配程度的度量。
理想折扣累积增益
(
I
D
C
G
n
)
(IDCG_n)
(IDCGn)
IDCG 是在假设与参考文本完美匹配的情况下,
n
n
n 元组可能达到的最大 DCG 值。它的计算方式与 DCG 类似,但将
n
n
n 元组按其最高相关性得分排序。通过比较
D
C
G
n
DCG_n
DCGn 与
I
D
C
G
n
IDCG_n
IDCGn,可以衡量生成文本与理想相关性的接近程度。
BLEU 分数及其变体在软件漏洞检测与缓解中的应用:
- BLEU 分数
- 用途:通过将 LLM 生成的代码与参考解决方案进行比较,评估其修复漏洞的整体质量。
- 示例:如果一个 LLM 为漏洞生成了一个补丁,BLEU 分数会衡量生成的补丁在单词/标记重叠方面与参考补丁的接近程度。
- BLEU-4
- 用途:通过考虑高达 4 元组的内容,提供更细致的评估,捕捉代码片段的局部结构和语义连贯性。
- 示例:在解决缓冲区溢出漏洞时,BLEU-4 可以评估生成的代码是否正确处理多标记结构(如边界检查和数组索引)。
- BLEU-DC
- 用途:扩展了 BLEU,通过考虑代码不同部分的重要性,特别适用于评估某些部分比其他部分更重要的漏洞补丁。
- 示例:在缓解 SQL 注入漏洞时,BLEU-DC 可以强调输入验证和清理的正确性,而非关键部分则相对次要。
11.3.4 CodeBLEU
CodeBLEU 是广泛使用的 BLEU 指标的扩展,专门用于评估代码生成任务的质量。它由 Ren 等人 [132] 首次提出,结合了传统 BLEU 分数以及捕获代码语法和语义方面的额外组件。在软件漏洞检测与缓解的背景下,CodeBLEU 通过同时考虑生成补丁或代码片段的正确性和对最佳编码实践的遵守,提供更全面的评估 [132]。
总体 CodeBLEU 分数是其四个组成部分的加权和。其中,加权 n n n 元组匹配和语法 AST 匹配用于衡量语法正确性,而 n n n 元组匹配则强调语言模式的直接重叠,确保生成的代码不仅语法正确,还紧密反映了示例代码的结构和措辞。这种双重关注有助于确保流畅性和对预期编码规范的忠实度。最后,语义数据流匹配用于计算逻辑正确性。
CodeBLEU=α⋅n-grammatch(BLEU)+β⋅Weighted n-gram Match+γ⋅Syntactic AST Match+δ⋅Semantic Data-Flow Match
其中:
- α , β , γ , δ \alpha, \beta, \gamma, \delta α,β,γ,δ:为每个组件分配的权重(根据任务可定制)。
- n n n-gram 匹配(类似于 BLEU):衡量生成代码与参考代码片段的接近程度,使用标准 BLEU 公式计算。
- 加权 n n n-gram 匹配:指传统 n n n-gram 匹配的改进版本(如 BLEU 中使用),为不同的 n n n-gram 赋予权重。这意味着并非所有 n n n-gram 都被平等对待;相反,某些 n n n-gram 根据其在代码生成上下文中的重要性被赋予更高的权重。
- AST 匹配:通过抽象语法树(ASTs)评估生成代码与参考代码之间的结构相似性。
Syntax Match = Number of matching AST nodes Total number of AST nodes in the reference \text{Syntax Match} = \frac{\text{Number of matching AST nodes}}{\text{Total number of AST nodes in the reference}} Syntax Match=Total number of AST nodes in the referenceNumber of matching AST nodes - 数据流匹配:捕捉变量和数据使用的一致性,还评估代码中的数据流,确保变量及其使用被正确处理。
Data Flow Match = Number of matching data flow nodes Total number of data flow edges in the reference \text{Data Flow Match} = \frac{\text{Number of matching data flow nodes}}{\text{Total number of data flow edges in the reference}} Data Flow Match=Total number of data flow edges in the referenceNumber of matching data flow nodes
11.3.5 Pass@k
Pass@k 是一种常用的评估指标,用于评估 LLM 在代码生成、软件漏洞检测和缓解等任务中的性能。它衡量前 k k k 个生成解决方案中至少有一个正确的可能性。该指标在模型生成多个候选解决方案的场景中特别有用,目标是确定这些候选方案中有多少次至少有一个是正确的 [32]。
P a s s @ k = E Problems [ 1 − ( n − c k ) ( n k ) ] Pass@k = \mathbb{E}_{\text{Problems}} \left[ 1 - \frac{\binom{n-c}{k}}{\binom{n}{k}} \right] Pass@k=EProblems[1−(kn)(kn−c)]
其中:
- E Problems \mathbb{E}_{\text{Problems}} EProblems:问题期望值,表示数据集中所有问题的平均值。
- n n n:模型为给定任务生成的样本总数,代表评估期间考虑的所有可能输出。
- c c c: n n n 个样本中正确的样本数。正确的样本是指通过所有单元测试或满足评估标准的样本。
- k k k:用于评估的前 k k k 个样本的数量。这定义了生成样本中有多少被评估为正确。
-
(
a
b
)
\binom{a}{b}
(ba):二项式系数,表示从
a
a
a 个项目中选择
b
b
b 个项目的方式数量,不考虑顺序。
( a b ) = a ! b ! ( a − b ) ! \binom{a}{b} = \frac{a!}{b!(a-b)!} (ba)=b!(a−b)!a! - 1 − ( n − c k ) ( n k ) 1 - \frac{\binom{n-c}{k}}{\binom{n}{k}} 1−(kn)(kn−c):计算至少一个 k k k 样本正确的概率。
- ( n − c k ) \binom{n-c}{k} (kn−c):从 n − c n-c n−c 个错误样本中选择 k k k 个错误样本的方式数量。
- ( n − c k ) ( n k ) \frac{\binom{n-c}{k}}{\binom{n}{k}} (kn)(kn−c):从 n n n 个样本中选择 k k k 个错误样本的概率。
Pass@k 的局限性
- 对 k k k 值的依赖性: k k k 的选择对结果有很大影响。较大的 k k k 值可能会夸大指标,即使大多数输出不正确,模型也可能更容易“通过”。相反,较小的 k k k 值可能会低估模型的能力,特别是当正确解决方案始终略微超出前 k k k 名时。
- 未惩罚错误输出:Pass@k 不考虑生成输出中错误的数量或严重性。例如,如果模型生成 k − 1 k-1 k−1 个错误输出和 1 个正确输出,该指标将其视为成功,而不考虑这些错误输出的潜在后果。
- 侧重语法而非语义:Pass@k 通常依赖严格的正确性标准,例如精确的语法匹配或通过单元测试,但它不评估生成代码的语义正确性或质量。
- 执行要求:需要执行生成的代码,这在所有环境中可能都不可行。
11.3.6 完全匹配 (EM)
完全匹配(Exact Match, EM)指标用于评估大型语言模型(LLMs)在文本生成任务中的性能,包括软件漏洞检测与缓解领域。EM 衡量模型生成的输出是否与真实值或参考输出完全匹配(即正确预测的答案中有多少百分比与真实答案完全一致)。它特别适用于对精度要求较高的任务,例如识别特定漏洞、生成缓解脚本或将漏洞映射到特定模式 [135]。
EM 指标本质上是二元的,这意味着如果模型的输出与真实值完全匹配,则结果为 1;否则为 0 [135]。
在软件漏洞检测的背景下,EM 可用于评估模型在以下任务中的准确性:
- 生成漏洞的精确标识符。
- 生成复制给定解决方案的代码片段。
- 提供漏洞与缓解技术之间的精确映射。
EM 的局限性
- 无部分得分:EM 不考虑部分正确的输出,即使输出接近参考值但未能完全匹配,也会得分为 0。
- 过度依赖格式:轻微的格式差异可能导致 EM 得分为 0,即使核心信息正确。
- 不考虑同义词:在文本输出中,语义等价但词汇不同的响应不会被视为匹配。
11.3.7 ROUGE/ROUGE-L
ROUGE(Recall-Oriented Understudy for Gisting Evaluation)是一种自动评估方法,通过将计算机生成的摘要与人类创建的理想摘要进行比较来确定摘要质量。ROUGE 测量计算机生成摘要与参考摘要之间重叠的单元数,例如 n n n-gram、词序列和词对。ROUGE 包括四种主要度量:ROUGE-N、ROUGE-L、ROUGE-W 和 ROUGE-S。这些指标已用于各种大规模摘要评估,包括文档理解会议(DUC)[136]。在软件漏洞检测与缓解领域,ROUGE 指标可用于评估语言模型生成描述、代码片段或缓解策略与参考输出的匹配程度。为了本研究的目的,我们将重点关注最广泛使用的 ROUGE-N 和 ROUGE-L。有关 ROUGE 的更全面分析,请参阅 Chin-Yew Lin 的研究 [136]。
ROUGE-N
ROUGE-N 测量生成文本与参考文本之间
n
n
n-gram 的重叠。它主要以召回率为导向,衡量生成文本捕获了多少参考文本中的
n
n
n-gram。ROUGE-N 的公式为:
R
O
U
G
E
−
N
=
∑
S
∈
Reference Summaries
∑
n
-gram
∈
S
Count
match
(
n
-gram
)
∑
S
∈
Reference Summaries
∑
n
-gram
∈
S
Count
(
n
-gram
)
ROUGE-N = \frac{\sum_{S \in \text{Reference Summaries}} \sum_{n\text{-gram} \in S} \text{Count}_{\text{match}}(n\text{-gram})}{\sum_{S \in \text{Reference Summaries}} \sum_{n\text{-gram} \in S} \text{Count}(n\text{-gram})}
ROUGE−N=∑S∈Reference Summaries∑n-gram∈SCount(n-gram)∑S∈Reference Summaries∑n-gram∈SCountmatch(n-gram)
其中:
- Count match ( n -gram ) \text{Count}_{\text{match}}(n\text{-gram}) Countmatch(n-gram):生成输出中同时出现在参考输出中的 n n n-gram 的最大数量。
- Count ( n -gram ) \text{Count}(n\text{-gram}) Count(n-gram):参考输出中 n n n-gram 的总数。
- ∑ S ∈ Reference Summaries \sum_{S \in \text{Reference Summaries}} ∑S∈Reference Summaries:对所有参考摘要求和。
ROUGE-L
ROUGE-L 基于最长公共子序列(LCS)测量两段文本之间的相似性。与基于
n
n
n-gram 的指标不同,它捕获顺序匹配而不要求严格的邻接关系。ROUGE-L 使用三个公式计算精确率、召回率和 F1 分数:
- 召回率(
R
L
C
S
R_{LCS}
RLCS):
Recall ( R L C S ) = LCS ( X , Y ) Length of X \text{Recall}(R_{LCS}) = \frac{\text{LCS}(X, Y)}{\text{Length of } X} Recall(RLCS)=Length of XLCS(X,Y) - 精确率(
P
L
C
S
P_{LCS}
PLCS):
Precision ( P L C S ) = LCS ( X , Y ) Length of Y \text{Precision}(P_{LCS}) = \frac{\text{LCS}(X, Y)}{\text{Length of } Y} Precision(PLCS)=Length of YLCS(X,Y) - F1 分数(
F
L
C
S
F_{LCS}
FLCS):
F1-score ( F L C S ) = ( 1 + β 2 ) ⋅ R L C S ⋅ P L C S R L C S + β 2 ⋅ P L C S \text{F1-score}(F_{LCS}) = \frac{(1 + \beta^2) \cdot R_{LCS} \cdot P_{LCS}}{R_{LCS} + \beta^2 \cdot P_{LCS}} F1-score(FLCS)=RLCS+β2⋅PLCS(1+β2)⋅RLCS⋅PLCS
其中:
- X X X 是参考摘要句子, Y Y Y 是候选摘要句子。
- LCS ( X , Y ) \text{LCS}(X, Y) LCS(X,Y) 是 X X X 和 Y Y Y 的最长公共子序列的长度。
- β \beta β 是 ROUGE-L 分数中的参数,用于控制精确率和召回率的相对重要性。当 β = 1 \beta = 1 β=1 时,ROUGE-L 分数是精确率和召回率的调和平均值;如果 β > 1 \beta > 1 β>1,则召回率比精确率更重要。
ROUGE 的局限性
- 关注表面匹配,忽略语义准确性。
- 对格式化和分词问题过于敏感。
- 无法评估代码的逻辑或功能正确性。
这些评估 LLM 性能的方法认识到软件工程(SE)任务的复杂性,采用针对具体任务量身定制的指标,无论是分类、推荐还是生成任务,都能全面衡量模型的有效性和准确性。尽管这些指标很有用,但其局限性突显了结合互补指标和定性评估的重要性,以获得对模型性能的更全面了解。例如,将 Pass@k 与完全匹配(EM)、BLEU 或 CodeBLEU 等指标结合使用,并进行人工错误分析,可以更深入地了解模型的优势和劣势。
RQ9 回答:
用于评估 LLM 在解决软件漏洞和网络威胁方面的指标包括:
- 分类任务:F1 分数、精确率、召回率、准确率和 AUC-ROC。
- 推荐任务:MRR、F1-score@k、Precision@k、Recall@k、Accuracy 和 Accuracy@k。
- 生成任务:代码覆盖率、准确率、BLEU、CodeBLEU、完全匹配、ROUGE/ROUGE-L 和 Pass@k。
这些指标提供了对 LLM 在软件安全领域各类任务中的性能的全面评估。每个评估指标都有其独特的优势和局限性,使其适用于评估 LLM 在应对软件漏洞方面的特定方面。例如,分类指标如精确率和召回率在量化检测真正类与避免假阳性之间的平衡方面特别有效,这对识别安全漏洞至关重要。另一方面,生成指标如 BLEU 和 CodeBLEU 专注于生成代码的语法和语义准确性,从而为模型生成上下文和功能正确的输出提供了洞察。像 Pass@k 这样的指标则评估在前 k 次尝试中生成至少一个正确解决方案的可能性,这对于评估模型在代码补全或修复任务中的表现尤为重要。
12 RQ10:在软件漏洞检测中使用 LLM 的挑战是什么?
与使用 LLM 进行软件安全相关的局限性或挑战有哪些?如何缓解这些问题?在本节中,我们将尝试解答这一问题。
提示注入攻击(Prompt Injection Attacks)
提示注入攻击是与 LLM 相关的重要安全问题之一 [69, 84, 103]。提示注入攻击涉及操纵提供给 LLM 的输入提示,以诱使其生成有害、未经授权或泄露敏感信息的响应。恶意用户可能试图欺骗 LLM,生成可能危及安全、侵犯隐私或造成其他危害的输出。这些攻击利用了 LLM 在处理提示时的漏洞,可能导致破坏性后果或安全漏洞。这种攻击形式尤其在 LLM 集成应用中具有强大威胁性,最近被 OWASP(开放 Web 应用安全项目)基金会认定为与 LLM 相关的主要威胁。此类操纵可能导致负面后果,例如提供错误指导或未经授权泄露机密数据 [61, 137, 138]。
提示注入的重要性在于,它突显了随着我们进一步进入 LLM 时代,解决提示滥用和提示泄露问题的必要性。保护 LLM 集成应用免受提示注入威胁至关重要,许多开发者已表现出对此问题的日益警惕,并在实施提示保护系统和寻找新解决方案方面做出了努力 [61, 137, 138]。
提示注入攻击分为两类:
- 直接提示注入:通常被称为“越狱”,直接提示注入涉及篡改或暴露系统提示,往往导致部分知识产权的损失。此过程可能包括创建提示,以绕过 LLM 创建者实施的安全和审查措施 [138]。
- 间接提示注入:当 LLM 接受来自可被攻击者操纵的外部来源(如网站或文件)的输入时,会发生间接提示注入。在这种情况下,攻击者可以欺骗 LLM 将其输入解释为“命令”而非“数据”进行处理,从而导致基于 LLM 的应用程序行为异常或危及整个系统的安全性 [138]。
漏洞检测挑战
由于 LLM 能够为同一问题生成多种替代响应,因此使用 LLM 检测漏洞可能会存在问题。这种多样性虽然在语言处理和文本生成中有益,但在定位实际漏洞时可能带来挑战。尽管多种解决方案在某些情况下是有利的,但它也可能使识别最简单的软件安全漏洞变得复杂 [17]。
LLM 代码生成挑战
LLM 在面对多种有效解决方案时可能难以生成准确的代码,从而导致功能正确但上下文不合适的代码。它们可能在特定训练任务上表现良好,但在未训练过的任务、语言或领域中表现不佳。当输入经历保持语义的转换时,其性能可能会显著下降 [16, 131]。
一项研究 [59] 分析了 2033 个编程任务和 4066 个 ChatGPT 生成的代码片段(用 Java 和 Python 实现),其中 2556 个代码存在质量问题,以全面评估 AI 生成代码的质量并揭示影响性能的因素。尽管 ChatGPT-3.5 可以为各种任务生成功能性代码,但研究结果揭示了 ChatGPT-3.5 生成代码中的一系列质量问题,包括编译和运行时错误、错误输出以及可维护性问题。这一发现强调了需要认真解决这些问题,以确保 AI 驱动的代码生成的持续有效性,并维持高质量软件系统的标准。
幻觉问题(Hallucinations)
LLM 经常生成虚假信息,称为“幻觉”,这些信息在统计上看似合理。研究表明,结合外部知识和自动化反馈机制可以缓解这些幻觉 [77, 89, 138]。
代码质量问题
代码质量问题因其可能造成的财务和声誉损失而备受关注 [37, 59, 80]。
LLM 部署挑战
LLM 在软件开发中已成为重要工具,但它们也带来了自身的挑战。其庞大的规模需要大量资源,使得在资源有限的情况下部署变得困难。它们高度依赖大规模且多样化的训练数据集,而有限或有偏差的数据可能导致预测不准确。此外,训练数据中可能包含个人身份信息(PII),引发隐私泄露的担忧 [16]。
LLM 评估挑战
现有的评估指标可能无法捕捉模型性能的所有方面,例如可解释性、鲁棒性或对某些错误的敏感性。LLM 在决策过程中通常缺乏可解释性和透明性,导致开发者对其产生不确定性。此外,围绕训练数据所有权、衍生数据以及通过植入漏洞发起对抗性攻击的担忧仍然存在 [16]。
在软件漏洞和网络安全领域比较 LLM 性能时,一个关键问题是如何公平地进行比较,因为不同场景下的测试条件可能存在差异。例如,系统鲁棒性可能在使用相同数据集进行训练和测试时显著影响 LLM 的性能。值得注意的是,并非所有研究人员都能访问超级计算机或高性能工作站,这可能影响模型训练和评估的可扩展性和效率。此外,随着时间推移对数据集的更改或在测试期间选择性使用数据集的特定部分可能引入额外的变异性,从而影响比较分析的结果。
不安全的输出管理(Insecure Output Management)
开发者需要小心,因为 LLM 可能会生成有害的输出。如果不正确验证或清理 LLM 输出就使用,可能会导致安全风险,例如浏览器中的跨站脚本(XSS)和跨站请求伪造(CSRF)。此外,忽略验证 LLM 输出可能导致下游安全漏洞,包括危及系统的代码执行和数据泄露。攻击者还可以利用这些输出进行权限提升和后端系统的远程代码执行 [70, 138]。
训练数据中毒(Training Data Poisoning)
训练数据中毒是指故意操纵用于训练模型的数据,以达到恶意目的。对手在预训练或微调期间将欺骗性或有偏见的示例插入训练数据集中,以影响模型的学习过程。这可能涉及引入后门、偏差或其他漏洞,从而危及模型的安全性、性能和可靠性 [70, 138]。被操纵的训练数据可能扰乱 LLM 模型,导致响应可能危及安全性、准确性或道德行为。
拒绝服务模型(Denial of Service Model)
训练和运行大型模型(LMs)需要大量资源。攻击者可以通过与 LMs 交互的方式,使其过度消耗资源,从而降低服务质量,甚至拒绝为其他用户提供服务,并增加计算成本。攻击者可以创建在上下文长度或语言模式上计算密集的提示 [70, 97, 138]。
供应链漏洞(Supply Chain Vulnerabilities)
供应链涵盖了从收集数据和训练模型到其部署的完整过程。该过程包括训练数据、预训练模型和部署基础设施等不同元素。每个元素都容易受到漏洞的影响:众包训练数据可能被污染,预训练模型可能被破坏,或者在 LLM 开发中使用的第三方包可能不安全。根据受影响的组件、服务或数据集,它们会破坏系统完整性,导致数据泄露和系统崩溃 [138]。
敏感信息泄露(Disclosure of sensitive information)
LLM 最初是在包含真实世界信息片段的多样化数据集上训练的。在生成响应时,这些模型可能会无意中泄露敏感信息。例如,像 OpenAI 的 ChatGPT 和 Google 的 Gemini 等对话代理会在交互过程中收集用户提示以提高性能。然而,这种方法存在安全和隐私风险,因为模型可能无意中生成揭示机密或私人信息的输出。此外,通过精心构造的提示,攻击者可以故意利用这一漏洞来暴露敏感细节。未能保护 LLM 输出中的敏感信息泄露可能导致法律后果或竞争优势的丧失 [35, 138]。
不安全的插件设计(Insecure Plugin Design)
缺乏适当访问控制或输入验证的 LLM 插件可能导致诸如 SQL 注入和远程代码执行等漏洞。这些插件通常将用户输入视为无限制的文本,使其容易被攻击者利用 [138]。
过度授权(Too Much Agency)
基于 LLM 的系统根据用户提示或来自集成组件的输入做出决策。赋予 LLM 过多自主权或权限可能引入易受恶意行为者利用的漏洞,从而危及整个系统的安全性。即使没有蓄意攻击,意外的用户提示或关联系统的错误操作也可能导致 LLM 生成误导性或不可预见的输出,从而引发系统故障。例如,考虑一个基于 LLM 的文件摘要工具,它使用第三方插件访问用户文件。该插件除了具备读取功能外,还可能具有修改和删除文件的功能。如果用户在 LLM 摘要中发现问题并尝试向应用报告错误,这可能会无意中触发 LLM 修改或删除原始文件,突显了潜在的意外后果。最终,给予 LLM 不受限制的自主权可能导致损害可靠性、隐私和信任的意外后果 [138]。
过度依赖(Overreliance)
将这些模型用于源代码生成可能会无意中引入安全漏洞。这些漏洞可能对应用程序及其用户的安全构成重大威胁。未经适当审查就盲目应用 LLM 生成的信息或代码,可能导致一系列负面后果。这些后果包括安全漏洞、虚假信息传播、通信中断、法律问题和声誉损害 [138]。
模型盗窃(Model Theft)
未经授权复制或提取闭源 LLM 的权重、参数或数据构成了知识产权盗窃的一种形式。这种非法行为可能对开发者造成重大经济损失,并损害品牌声誉,最终危及公司的竞争优势。犯罪分子可能利用窃取的专有信息谋取私利,或将被盗模型用于恶意目的 [138]。
重要的是要认识到人工智能技术带来的机遇与威胁。我们必须承认 LLM 的变革潜力,但同时也要接受随之而来的新兴风险。随着 LLM 的不断发展,理解并控制相关风险的需求也在同步增长。通过缓解 AI 系统固有风险,在各个领域最大化自动化效益并增强功能的关键在于有效降低风险。为了有效减少风险,提高意识和准备至关重要。软件工程师(SE)通过分析过去的方法并将这些经验融入安全数据和系统机制中,发挥着至关重要的作用。新技术不断涌现,用于监控威胁并减轻风险。作为 AI 设计和开发的先驱,软件工程师有责任识别新漏洞并实施保护措施以保护用户。
RQ10 回答:
在网络安全任务中使用 LLM 的挑战包括但不限于:提示注入攻击、漏洞检测困难、代码生成挑战、幻觉问题、部署障碍、评估局限性、不安全的输出管理、数据中毒风险、拒绝服务、供应链漏洞、敏感信息泄露、不安全的插件设计、不受限制的自主权、过度依赖以及模型盗窃。这些挑战强调了理解并缓解与 LLM 相关风险的重要性,以在各种应用中最大化其优势,同时确保安全性和可靠性。
14 RQ11. 如何提升 LLM 在软件漏洞检测中的有效性?
与现有工具集成
为了增强软件漏洞和网络威胁检测,LLM 可以有效地与互补方法和工具结合使用。静态代码分析器擅长检测已知漏洞和编码错误,而动态分析工具(如模糊测试工具)则能够发现运行时漏洞。将 LLM 集成到安全测试框架和威胁情报平台中,可以实现全面的漏洞检测和主动的威胁缓解。
人类专业知识对于领域特定知识和 LLM 生成结果的验证仍然至关重要。LLM 还可以与 BMC(基于模型的检查)结合,创建自动化的代码修复框架。
集成 LLM 的持续监控系统能够快速检测和响应事件。协作平台促进知识共享和协调努力,以解决安全问题。通过结合这些方法,组织可以实现全面覆盖并提高软件漏洞和网络威胁检测的有效性。
更大且更多样化的数据集
在多种编程语言中对更广泛范围的漏洞代码和非漏洞代码进行 LLM 训练,可以增强其泛化能力并识别未见过代码中的漏洞。然而,鉴于在大规模数据集上训练 LLM 的挑战,也有研究致力于通过在较小数据集上训练来提高 LLM 的准确性。我们相信实现这一目标可以显著提升 LLM 的公共可用性。
专注于特定漏洞
在某些场景中,针对特定类型的漏洞训练 LLM 数据集可以提高其检测这些漏洞的准确性,但这种方法最适合仅易受特定攻击影响的系统。
预处理技术
构建代码片段(code gadgets)等技术可以帮助 LLM 区分实际漏洞与无关模式。
提示工程(Prompt Engineering)
设计有效的提示以引导 LLM 执行漏洞检测任务,从而提高焦点和准确性 [15]。
持续学习(Continuous Learning)
定期使用新的漏洞和威胁数据更新 LLM,以增强对新兴安全风险的检测能力。努力优化模型规模、提高数据多样性和质量、改进模糊场景中的代码生成能力、增强泛化能力、开发更好的评估方法,并专注于 LLM 的可解释性和道德使用。通过结合这些策略,我们可以充分释放 LLM 的潜力,使其成为应对软件漏洞和网络威胁的强大工具。
RQ11 回答:
为了提升 LLM 在软件漏洞和网络威胁检测中的有效性,组织可以将它们与现有工具(如静态代码分析器和动态分析工具)集成。此外,通过在更大且更多样化的数据集上训练 LLM、专注于特定漏洞以及采用预处理技术,可以提高其准确性。设计有效的提示、确保通过新数据进行持续学习、优化模型规模和数据质量至关重要。开发更好的评估方法并优先考虑可解释性和道德使用,将进一步释放 LLM 在应对软件漏洞和网络威胁方面的全部潜力。
15 结论
在这篇文章中,我们探讨了 LLM 的潜力,研究了它们在整个软件开发生命周期(SDLC)中的各种应用,特别是在软件漏洞检测和缓解方面。
我们的分析表明,当 LLM 得到适当训练并与现有工具集成时,可以显著增强软件安全性。LLM 在漏洞检测方面优于传统的静态代码分析器,并能够提出潜在修复方案,从而减轻开发人员的负担。此外,它们处理和理解自然语言的能力使它们能够分析日志和报告中的文本信息,帮助识别威胁并响应事件。然而,重要的是要认识到 LLM 的局限性。
随着 LLM 技术的不断发展,其在软件安全领域的应用也将不断扩展。通过解决当前的局限性并实施最佳实践进行训练和集成,LLM 有潜力彻底改变我们应对软件安全的方式,推动更安全、更强大的系统开发。
16 未来研究方向
未来的研究工作应集中在解决关键挑战上,以增强 LLM 在软件漏洞检测中的鲁棒性和可靠性。
1. 提高可解释性和透明性
LLM 仍然被视为黑箱系统,因为其内部工作机制尚未完全被理解和透明化。这种缺乏透明性的情况对理解这些模型如何得出结论提出了重大挑战。提高可解释性和透明性至关重要,原因如下:首先,它有助于建立用户和利益相关者的信任;其次,更大的透明性可以帮助识别和缓解模型中可能存在的偏差;最后,这一领域的进步可能会带来更强大和可靠的 AI 系统,因为开发者可以根据对其内部机制的清晰理解来优化和完善模型。引入诸如基于注意力机制的技术 [139]、SHapley 加性解释(SHAP)[140, 141]、局部可解释模型无关解释(LIME)[140, 142] 和多样化反事实解释(DiCE)[140, 143] 等技术,可以显著帮助解释 LLM 的决策,尤其是在复杂的漏洞评估中。
2. 领域适应
研究如何让 LLM 在不同的编程语言和环境中泛化是必要的,以防止在遇到不熟悉的任务或语义变化时性能下降。这种适应性将确保 LLM 在多样化的编码场景中保持有效性。
3. 持续学习
持续学习是一个有前景的方向。实施增量学习机制并整合实时威胁情报,可以帮助 LLM 跟上不断演变的威胁,减少对过时信息的依赖。强化学习从人类反馈(RLHF)等技术可以进一步增强适应性,使模型对新漏洞更具响应能力。
4. 应对安全威胁
应对提示注入攻击等安全威胁至关重要。研究重点应放在鲁棒的输入验证、对抗性训练和提示过滤机制上,以减轻这些风险。建立由 OWASP 等组织认可的标准化防御措施,将进一步加强针对直接和间接提示注入的保护。
5. 减少幻觉问题
利用外部知识库和反馈回路进行交叉验证可能是有效的。将自动化验证步骤集成到 LLM 工作流程中,可以提高准确性和可靠性,从而最大限度地减少此类错误的影响。
6. 解决部署挑战
需要特别关注优化 LLM 架构以适应资源受限的环境,并探索隐私保护技术(如联邦学习)。确保 LLM 供应链的安全并解决数据中毒风险,对于实现安全可靠的部署至关重要。
7. 改进评估指标
改进评估指标至关重要。开发全面的框架,不仅评估准确性,还评估可解释性、鲁棒性和公平性,将为 LLM 在实际应用中的表现提供更全面的视角。
这些进步将有助于弥合理论研究与实际部署之间的差距,使 LLM 成为更可靠的软件安全工具。协作努力和在这些领域的持续研究将推动重大进展,并激发进一步创新。
17 术语表
-
适配器(Adapters):集成到预训练语言模型中的小型可训练模块,用于在不改变核心模型参数的情况下实现高效的特定任务微调。
-
应用程序编程接口(API, Application Programming Interface):一组规则和工具,允许不同的软件程序相互通信。
-
自动程序修复(APR, Automatic Program Repair):一种无需人工干预即可自动修复软件错误的技术。
-
双向编码器表示(BERT, Bidirectional Encoder Representations from Transformers):一种用于理解自然语言处理任务中单词上下文的机器学习模型。
-
双语评估替代(BLEU, Bilingual Evaluation Understudy):通过与人工翻译进行比较来评估机器翻译质量的指标。
-
有界模型检查器(BMC, Bounded Model Checker):一种通过探索固定范围内的所有可能状态来检查软件漏洞的工具。
-
动态应用安全测试(DAST, Dynamic Application Security Testing):通过模拟攻击来测试运行中应用程序安全性的方法。
-
多样化反事实解释(DiCE, Diverse Counterfactual Explanations):一种在 AI 中提供替代输出并解释决策的技术。
-
编码器与解码器(Encoder & Decoder):编码器将各种输入(如文本、音频或图像)转换为称为潜在向量的压缩格式;解码器则相反,将这种压缩表示转换回其原始形式或类型。
-
少样本学习(Few-shot Learning):一种机器学习方法,使用少量标记数据训练模型以处理新任务。在 LLM 中,通常通过在输入提示中包含少量示例来实现,也称为上下文学习(in-context learning)。
-
微调(Fine-tuning):在预训练模型的基础上,进一步针对更具体或更小的数据集进行训练,以提高其在特定任务或领域中的性能。
-
通用语言理解评估(GLUE, General Language Understanding Evaluation):一个基准套件,用于评估 NLP 模型在多种语言理解任务中的表现,例如情感分析和自然语言推理。
-
交互式应用安全测试(IAST, Interactive Application Security Testing):一种通过监控应用程序执行过程来分析其安全性的工具。
-
长短期记忆网络(LSTM, Long Short-Term Memory):一种擅长处理序列(如时间序列数据或文本)的神经网络类型。
-
低秩适应(LoRA, Low-Rank Adaptation):一种通过调整小规模低秩矩阵来微调预训练模型的方法,从而保留大部分原始模型的参数。
-
宏数据优化(MDR, MacroData Refinement):组织和改进大规模数据的过程,以便更好地分析或使用。
-
平均倒数排名(MRR, Mean Reciprocal Rank):衡量系统在结果列表中正确排名的指标。
-
多任务学习(MTL, Multi-task Learning):一种让模型同时执行多个任务的机器学习技术,利用相关任务的信息提高其在所有任务上的泛化能力。
-
神经机器翻译(NMT, Neural Machine Translation):一种基于神经网络的文本翻译方法。
-
国家漏洞数据库(NVD, National Vulnerability Database):美国政府关于软件漏洞信息的数据库。
-
自然语言处理(NLP, Natural Language Processing):AI 领域的一个分支,专注于计算机与人类语言之间的交互,涵盖语言生成、翻译和情感分析等任务。
-
参数(Parameters):LLM 训练期间调整的内部值,如权重和偏置。权重影响神经元之间的连接,而偏置在激活前修改输入值。参数总数反映了 LLM 的复杂性和容量。
-
高效参数微调(PEFT, Parameter Efficient Fine-Tuning):一种通过仅修改部分参数来适应大型 AI 模型的技术,从而减少资源消耗。
-
前缀微调(Prefix-Tuning):一种软提示微调方法,在每个模型层的输入前附加一个可训练序列,从而增强对特定任务的适应性。
-
提示(Prompt):提供给 LLM 的输入文本或查询,用于生成相关输出或响应。
-
提示工程(Prompt Engineering):设计和优化输入提示以从 LLM 获得特定期望响应的实践。
-
程序依赖图(PDG, Program Dependency Graph):显示程序各部分之间关系的图表,有助于理解其结构。
-
量化(Quantization):降低模型权重和激活精度的过程,通常从 32 位降低到 8 位或更低,以减少内存使用并提高计算效率。
-
量化 LLM(Quantized LLMs):经过量化以降低精度的大型语言模型,在内存和计算效率方面表现更优。
-
基于人类反馈的强化学习(RLHF, Reinforcement Learning from Human Feedback):一种训练 AI 的技术,其中人类通过提供反馈来指导模型的学习过程。
-
软件保证参考数据集(SARD, Software Assurance Reference Dataset):用于评估软件漏洞检测工具的测试用例集合。
-
静态应用安全测试(SAST, Static Application Security Testing):一种在不运行应用程序的情况下分析源代码漏洞的方法。
-
软件开发生命周期(SDLC, Software Development LifeCycle):规划、开发、测试和部署软件的过程。
-
SHapley 加性解释(SHAP, SHapley Additive exPlanations):一种通过分析特征贡献来解释机器学习模型决策的方法。
-
结构化查询语言(SQL, Structured Query Language):一种用于管理和操作数据库的语言。
-
超级通用语言理解评估(SuperGLUE, Super General Language Understanding Evaluation):一个用于测试 AI 模型语言理解和推理能力的基准。
-
标记(Token):LLM 处理的最小输入或输出单元。标记可以是单个单词、子词、字符或文本和代码的片段。
-
零样本学习(Zero-shot Learning):一种技术,模型可以基于先前知识准确预测训练期间未遇到的新任务或类别,而无需任何这些任务的标记数据。