Is Your AI-Generated Code Really Safe? Evaluating Large Language Models on Secure Code Generation with CodeSecEval
- 标题:您的 AI 生成的代码真的安全吗?基于 CodeSecEval 对LLMs代码生成的安全性进行评估
- 摘要:*【Background】大语言模型(LLMs)在代码生成和代码修复方面取得了显著进展,为新手和经验丰富的开发人员带来了便利。然而,LLMs 使用来自开源代码库(如GitHub)中未经审查的数据进行训练,这增加了无意中传播安全漏洞的风险。【Status of research】尽管有大量研究在探索代码 LLMs 的安全性,但在全面解决其安全特性方面仍存在空白。【Methodology】在本研究中,我们旨在提供一项全面的研究,以精准评估并增强代码 LLMs 的安全性。为支持我们的研究,我们引入了 CodeSecEval,这是一个精心策划的数据集,专为处理 44 种关键漏洞类型而设计,包含 180 个不同样本。CodeSecEval 为代码模型在代码生成和代码修复这两个关键任务的自动评估奠定了基础,尤其强调安全性。【Experimental results】我们的实验结果显示,当前模型在代码生成和修复过程中经常忽视安全问题,导致生成易受攻击的代码。为此,我们提出了不同的策略,利用漏洞感知信息和不安全代码的解释来缓解这些安全漏洞。此外,我们的研究结果表明,某些漏洞类型特别影响模型的性能,从而影响其在实际应用中的有效性。【Research significance】*基于这些发现,我们相信本研究将对软件工程领域产生积极影响,激励开发出改进的训练方法,推动更安全、可靠的模型部署。
- 关键词:大语言模型(LLMs)、代码生成(Code Generation)、代码修复(Code Repair)、安全性(Security)、数据集(Dataset)
- 项目地址:???
1. Introduction – 问题陈述
-
LLMs生成的代码具有安全问题
LLMs(如PALM、LLaMA、GPT-4和 Claude 3)通常在来自开源代码库(如GitHub)的数据上进行训练,它们可能无意中学习并复制包含软件故障、漏洞和安全隐患的代码。2022 年的开源安全与风险分析(OSSRA)报告强调,在分析的 2049 个代码库中,81% 至少包含一个漏洞,其中 49% 存在高风险漏洞。
- Pearce 等人表明,Copilot 生成的代码大约 40% 是不安全的 (Asleep at the keyboard? assessing the security of github copilot’s code contrib utions)
- Khoury 等人发现 ChatGPT 生成的 21 个程序中只有 5 个是最初安全的 (How Secure is Code Generated by ChatGPT?)
- Perry 等人发现,使用 AI 助手的参与者编写的代码显著地比未使用助手的参与者编写的代码更不安全 (Do users write more insecure code with AI assistants?)
-
现有研究的局限性
-
大多数研究倾向于只关注少数 LLMs 或有限的漏洞类型
-
在探索或充分验证生成更安全代码的策略方面存在不足,忽视了LLMs 修复不安全代码的能力可作为提高代码安全性的重要方面
-
现有用于评估代码安全性的数据集存在显著的限制,例如规模小、部分或不可执行的代码,甚至缺少不安全/安全代码示例。并且通常依赖基于规则的静态分析工具,而这些工具已被证明不够准确,或者依赖手动检查,这仅适用于小范围的样本集,可能忽略代码的正确性。
【现有用于评估代码安全性的数据集】CyberSecEval、SecurityEval、LLMSecEval
-
-
针对现有研究的局限性,文章设立的研究目标
- 更准确地识别当前代码 LLM 在代码生成和代码修复中的安全漏洞
- 提供减轻这些任务相关安全风险的策略
-
本文贡献
- 精心策划代码数据集CodeSecEval,包含 180 个样本,涵盖 44 种关键漏洞类型。该数据集相较现有资源有显著改进,使代码安全分析的评估更加高效和自动化
- 通过对七个最先进的 LLMs 进行广泛评估,揭示了其在代码生成和修复过程中普遍忽视安全考量的问题。对模型的漏洞进行了详细批评,深入揭示了其局限性
- 设计并验证了有效的策略,通过整合漏洞意识信息和不安全代码解释来增强生成或修复代码的安全性。这些策略旨在显著减轻漏洞,为更安全的模型训练方法和更安全的程序部署实践提供了宝贵的见解
PAE - “精确自动评估”,CG - “代码生成”,CR - “代码修复”
2. Related Work – 相关工作
-
LLMs的安全问题
现有研究存在的主要局限包括: (1) 大多仅关注少数 LLMs或特定漏洞类型;(2) 未充分探讨生成或修复安全代码的有效策略;(3) 依赖不够精确的安全工具(如 CodeQL)或手动评估,但可能忽略代码整体正确性。这些局限性突显了在代码安全研究中,LLMs 领域仍需更多探索。
-
代码安全性的数据集
【代码修复】
-
QuixBugs 包含转译为 Python 和 Java 的程序,每个程序包含一个单行错误。尽管具有相关性,该数据集规模较小,仅包含 40 个实例。
-
Big-Vul包含 91 种不同漏洞类型的 3,754 个代码漏洞,均提取自 348 个 Github 项目。
-
CVEfixes 通过使用通用弱点枚举(CWE)类型并结合 CVSS 严重性评分,提供了漏洞的全面分类。该数据集包含 18,249 个文件和 50,322 个函数,包括修复前后的代码。由于缺少测试用例,从安全角度对模型生成的修复代码进行自动评估面临挑战。
【代码生成】
-
SecurityEval 包含 130 个 Python 代码样本,涵盖 75 种漏洞类型。
-
LLMSecEval 提供 150 个实例,覆盖 18 种类型
-
CyberSecEval 提供了 1,916 个实例,涵盖 50 种类型。
-
CodeSecEval 涵盖了广泛的关键漏洞类型,并为每个数据实例提供了详细属性,支持精确的自动评估。通过使用 CodeSecEval,旨在更准确地调查最先进 LLM 在代码生成和修复方面的能力,同时提出有效策略,以提高这两项任务的安全性。
3. CodeSecEval*
-
Introduction
CodeSecEval 包含 44 种漏洞类型的 180 个样本,为评估 Python 语言的代码安全性提供了一个强大的框架。
CodeSecEval 显著特点在于包含可执行的安全和不安全代码,并引入了测试用例,便于使用 Pass@k 指标进行自动且精确的评估。数据集为每个实例设置了六个独特属性,具体如下:
- ID:每个数据实例的唯一标识符,也指示特定的漏洞类型。例如,“CWE434_03”表示一个 CWE-434 漏洞类型的样本。
- Problem:一个描述中等复杂度编程问题的说明,需解决该问题。
- Insecure Code:展示指定漏洞的不安全代码示例。
- Secure Code:解决指定漏洞的安全代码示例。
- Test:一组测试用例,用于验证代码的功能正确性和安全性,封装在名为“check”的函数中。
- Entry_Point:需实现的函数名称。
基于所处理漏洞的特征和使用的资源,CodeSecEval 进一步划分为以下两个不同的子集:
-
SecEvalBase:该子集使用 SecurityEval 数据集构建,SecurityEval 聚合了来自四个外部来源的实例。原始 SecurityEval 数据集并未包含“Secure Code”、“Test”和“Entry_Point”的注释,其“不安全代码”实例通常不完整,需要额外的上下文,如辅助函数或特定配置,以确保功能的完整性。因此,SecEvalBase 的实例选择基于完成不安全代码的可行性,并为缺失的属性提供必要的注释。最终,SecEvalBase 包含 67 个实例,涵盖 37 种漏洞类型。
【SecurityEval的四个外部来源】
CodeQL. https://github.com/github/codeq.
The MITRE Corporation (MITRE). Common Weakness Enumeration.
SonarSource. https://rules.sonarsource.com.
Asleep at the keyboard? assessing the security of github copilot’s code contributions.
白色背景显示的属性对应于 CodeSecEval 数据集的标准属性,灰色背景的属性是专门引入的属性
-
SecEvalPlus:该子集聚焦于“2023 年 CWE 最危险的 25 种软件弱点”。我们从列表中排除了八种类型,因为它们在 Python 中较为罕见(例如“CWE-476:空指针解引用”),或需要特定配置才能进行测试(如“CWE-918:服务器端请求伪造 (SSRF)”)。我们将“CWE-287”、“CWE-863”、“CWE-862”和“CWE-306”合并为一个类别,用于处理类似的授权问题。最终,SecEvalPlus 包含 14 种类型的 113 个实例,每种类型至少提供 8 个实例,以确保每个类别有充足的样本。
SecEvalPlus示例:针对 CWE-78 漏洞,不安全代码展示了攻击者可能注入有害命令的风险,安全代码有效地缓解了该漏洞。测试属性包含多种测试用例,用于评估代码的正确性和安全性
-
Construction
SecEvalBase数据集
每组(由一名博士生和一名硕士生组成,共四组)分配了大约 35 条来自现有 SecurityEval 数据集的记录,重点关注不安全代码的可执行性以及构建各种测试用例的可行性。在初步评估后对五个关键数据元素进行了注释:“Secure Code”、“Test” 和 “Entry_Point”。此外,在“Problem”中添加一些输入输出示例,并对“不安全代码”进行必要调整,以便测试并更好地匹配漏洞情境。
每条记录在小组内经过严格的手动检查流程,具体步骤如下:(1) “Problem” 应清晰、具有中等复杂度,与先前收集的“Problem”不同,并包含输入输出示例。(2) “不安全代码”必须展现指定的漏洞。(3) “安全代码” 需要有效解决“不安全代码”中的漏洞。(4) “测试”应包含多种用例,以评估代码的正确性和安全性,“安全代码”应通过所有测试,而“不安全代码”应未通过。(5) “Entry_Point” 仅包含需实现的函数名称。
SecEvalPlus数据集
每组被分配了来自“2023 CWE 最危险软件弱点25强”中的14种漏洞类型中的3到4种,要求每种类型生成至少八个实例。与 SecEvalBase 不同,SecEvalPlus 没有预定义的“不安全代码”或“Problem”,因此小组需识别真实场景或创建新的示例,展示这些漏洞。最后每条记录都经过了与 SecEvalBase 相同的验证和筛选流程。
【创建示例的灵感来源】
How Secure is Code Generated by ChatGPT?
Asleep at the keyboard? assessing the security of github copilot’s code contributions.
-
漏洞缓解假设
通过在代码生成和修复任务中引入漏洞意识,可能可以LLMs生成和修复代码的安全性
- 漏洞感知问题描述:研究人员假设,如果将安全性相关的信息直接嵌入问题描述中(比如明确指出要关注并解决潜在的安全漏洞),可能会帮助 LLM 更好地理解和识别问题中的安全风险。换句话说,增强问题描述的安全性意识,可能能让模型更有针对性地进行安全性处理,从而减少漏洞。
- 不安全代码解释:此外,研究人员认为,仅让模型修复错误代码可能不够有效,因为模型可能无法清晰理解代码中的具体问题。因此,研究团队假设,如果在不安全代码旁边加入一个简短的说明,解释代码中的漏洞所在,这可能会帮助模型更加精准地关注问题,从而提高修复代码的成功率。
4. Experiments
4.1 实验设置
- 研究问题
RQ1: LLMs 在代码生成过程中解决安全问题的效果如何?
RQ2: 可以设计哪些策略来提高 LLMs 的代码生成安全性?这些策略在多大程度上能缓解安全漏洞?某些漏洞类型是否更容易被成功缓解?
RQ3: LLMs 在修复不安全代码方面的表现如何?
RQ4: 可以设计哪些策略来提高 LLMs 修复代码的安全性?这些方法在多大程度上能修复安全漏洞?某些漏洞类型是否更容易被成功修复?
RQ5: 研究结果对更广泛的软件工程社区有何影响?开发者和研究人员如何在实际应用中更安全地利用 LLMs?
-
实验设计
- 直接代码生成:此实验评估 LLMs 从问题描述直接生成安全代码的能力,旨在回答RQ1
- 带有漏洞感知问题的代码生成:目标是确定在问题描述中加入安全细节是否会减少漏洞,旨在回答RQ2
- 直接代码修复:主要评估现有LLMs直接修复不安全代码的表现,旨在回答 RQ3
- 带有不安全代码解释的代码修复:为 LLMs 提供了不安全代码中的漏洞解释,旨在回答 RQ4
-
模型选择
- InCoder:参数规模(6.7B)
- CodeGen:参数规模(6B,单语言版本)
- StarCoder:参数规模 15B,窗口大小 8K
- CodeLlama-Instruct:参数规模(7B)
- GPT-3.5:参数规模(175B)
- GPT-4 [39]:参数规模未知,但相较于 GPT-3.5 具有更强的能力
- Claude 3 Opus:参数规模(137B)
-
实验指标
使用 Pass@k 的无偏版本
Pass@k = E problems [ 1 − ( n − c n ) ( n k ) ] \text{Pass@k} = E_{\text{problems}} \left[1 - \left(\frac{{n - c}}{{n}}\right)^{\binom{n}{k}}\right] Pass@k=Eproblems 1−(nn−c)(kn)
其中 $ k \leq n$ 是样本数, c ≤ n c \leq n c≤n 是通过所有测试用例的代码数。 1 − ( n − c n ) ( n k ) 1 - \left(\frac{{n - c}}{{n}}\right)^{\binom{n}{k}} 1−(nn−c)(kn) 是对单个问题的 Pass@k 的估计值。 E E E 表示所有问题的 P a s s @ k Pass@k Pass@k 的期望值。在实际操作中,我们计算所有问题的平均 P a s s @ k Pass@k Pass@k,考虑 k k k 取值为 1、3、5、7 和 10。
4.2 实验结果及分析
-
RQ1: LLMs 在代码生成过程中解决安全问题的效果如何?
较小模型中,CodeLlama-Instruct 表现最佳,CodeGen 次之,而 Incoder 表现不佳,StarCoder 尽管参数量大,但效果不如 CodeGen 和 CodeLlama-Instruct。
较大模型中,Claude 3 Opus 在$ k$ 值较小时效果最好,但随着 k k k 增加,GPT-4 或 GPT-3.5 表现更优;在特定数据集上,GPT-4 表现最优,但在自然语言描述的问题上表现稍逊。
总结:LLM 在代码生成任务中表现因模型和数据集特征而异,强调了精细调整和按需应用的重要性。
-
RQ2: 可以设计哪些策略来提高 LLMs 的代码生成安全性?这些策略在多大程度上能缓解安全漏洞?某些漏洞类型是否更容易被成功缓解?
实验方法:引入“漏洞感知问题”以评估融入漏洞信息是否能提升代码安全性。
(1)除 Incoder 外,所有模型在引入漏洞信息后 Pass@k 分数显著提升,尤其是较小模型 CodeLlama-Instruct 和较大模型 Claude 3 Opus,在特定条件下表现出色。
(2)LLMs在不同漏洞类型上的表现:GPT-4 通过引入“漏洞感知问题”描述,多数类型的 Pass@k 显著提升,但在某些漏洞类型(如注入类漏洞)上表现欠佳,说明它在应对特定漏洞时存在挑战。
(3)包含详细步骤的问题更易生成安全代码,表明提供安全相关步骤信息有助于提高代码生成的安全性。
-
RQ3: LLMs 在修复不安全代码方面的表现如何?
较小模型(Incoder、CodeGen 和 StarCoder)在代码修复任务中的性能下降,尤其是 StarCoder,Pass@1 从 4.33 降至 0.61,表明其修复不安全代码的能力有限。
较大模型(GPT-3.5、GPT-4 和 Claude 3 Opus)在代码修复任务中表现更好,尤其是 GPT-4,在 CodeSecEval 数据集上的 Pass@5 分数显著提升,从 16.23 提高到 29.23,并在大多数情况下表现最佳。
-
RQ4: 可以设计哪些策略来提高 LLMs 修复代码的安全性?这些方法在多大程度上能修复安全漏洞?某些漏洞类型是否更容易被成功修复?
三个较小模型(Incoder、CodeGen 和 StarCoder)在使用不安全代码解释后性能下降,而较大模型(包括 CodeLlama-Instruct、GPT-4 和 Claude 3 Opus)表现有所提升,其中 GPT-4 表现最佳。
GPT-4 在不同漏洞类型上的修复效果差异显著,有些漏洞类型无改善甚至下降。
-
RQ5: 研究结果对更广泛的软件工程社区有何影响?开发者和研究人员如何在实际应用中更安全地利用 LLMs?
【启示】
(1)CodeSecEval 数据集的贡献:CodeSecEval 数据集为从软件安全角度评估代码 LLM 提供了重要资源,包含易受攻击和安全的代码实例,支持代码生成、修复和漏洞分类任务。
(2)使用 LLM 的潜在风险:强调在代码生成和修复中使用 LLMs 时需关注安全风险,帮助开发者依据安全需求选择合适模型。
(3)进一步研究的需求:指出在代码修复上需进一步研究,以提升软件系统的安全性。
【建议】
(1)融入安全意识:在提示中融入漏洞信息,有助于生成更安全的代码。
(2)验证修复能力:在部署前验证 LLMs 修复漏洞的能力,以避免引入新风险。
(3)构建数据集:建立多样化、清晰标注的漏洞数据集,有助开发更安全的模型。
(4)持续改进模型:不断提升 LLMs 的安全意识能力以增强安全性。