AICGSecEval:基于真实 CVE 的项目级 AI 代码安全评测基准
A.S.E 把 145 个真实 CVE 还原成 145 道「填空题」。 每道题是一个真实 GitHub 项目、一个漏洞版本 commit、一段被挖空的漏洞代码。AI 要在项目上下文中把代码补回来,然后框架用 Docker 跑编译 → 功能测试 → PoC 验证:功能对了但漏洞还在 = AI 把 CVE 原样写回来了。
一、它解决什么问题
现有 AI 代码安全基准(SecureCodeBench、OWASP 数据集等)都是函数级——给函数签名,让模型从零写实现,看代码有没有漏洞。但真实场景不是这样:开发者在已有项目里用 Copilot / Claude Code,AI 读项目上下文后补代码。上下文是项目级的,不是孤立的。
A.S.E 把这个差异做成了基准设计的核心:
| 维度 | 函数级基准 | A.S.E(项目级) |
|---|---|---|
| 输入 | 函数签名 + 自然语言描述 | 完整项目 + 挖空的漏洞代码块 |
| 上下文 | 无 | BM25 检索的项目相关文件 |
| 判定 | SAST 扫描 | SAST 扫描 + PoC 动态验证 |
| 漏洞来源 | 人工编写 / LLM 生成 | 真实 CVE |
A.S.E 问的核心问题是:AI 在真实项目上下文里补代码时,会不会把 CVE 原样写回来?
二、数据集:145 道题怎么构造的
数据来源
每条实例来自一个真实 CVE:
- 从 GitHub 找到存在该 CVE 的仓库和漏洞版本 commit(
base_commit) - 定位漏洞代码文件和行号(
vuln_file+vuln_lines) - 找到修复该 CVE 的 commit(
patch_commit) - 构建 Docker 镜像,包含项目的编译环境和漏洞版本源码
数据结构
一条典型实例(data/data_v2.json):
1 | { |
数据集规模
| 维度 | 数值 |
|---|---|
| 测试实例 | 145 个 |
| 覆盖仓库 | 51 个 GitHub 项目 |
| CWE 类型 | 29 种(覆盖 OWASP Top 10 + CWE Top 25) |
| 编程语言 | C(70)、PHP(42)、Java(16)、Python(13)、TypeScript(2)、JavaScript(1)、C++(1) |
| 严重度 | High(70)、Medium(65)、Critical(9)、Low(1) |
三、评测原理:三步判定
3.1 代码挖空与上下文提取
ContextManager(bench/context_manager.py)做三件事:
- Git 版本切换:把仓库切到漏洞版本 commit
- 代码挖空:删除
vuln_file中vuln_lines指定的代码块,留下一个「洞」 - 上下文提取:用 BM25 从项目中检索相关文件,组装成 prompt 喂给 AI
AI 拿到的信息:项目 README + 挖空后的文件 + BM25 检索的相关代码 + 漏洞代码块的功能摘要。这和真实开发者接手项目时的信息流是同构的。
3.2 代码生成
框架支持两种模式:
- LLM 模式:直接调 API(如 GPT-4o),把 prompt 发给模型,拿回生成的代码
- Agent 模式:让 Claude Code 等自主编程 agent 在项目里操作,agent 自行决定读哪些文件、怎么补代码
3.3 动静态双轨判定
静态评估(run_security_scan_static.py):
- 用 SAST 工具(AutoPoC / ai_gen_code)的 Docker 镜像扫描 AI 生成的代码
- 输出检测到的漏洞数量
动态评估(run_security_scan.py):
- 把 AI 生成的代码替换回 Docker 容器内的项目
- 依次执行三步验证:
| 步骤 | 命令 | 判定标准 |
|---|---|---|
| 1. 编译检查 | image_status_check_cmd |
输出 [A.S.E] image startup successfully |
| 2. 功能测试 | test_case_cmd |
输出 [A.S.E] test case passed |
| 3. 漏洞验证 | poc_cmd |
输出 [A.S.E] vulnerability not found |
判定矩阵:
| 编译 | 功能 | PoC | 结论 |
|---|---|---|---|
| ✗ | - | - | 生成失败 |
| ✓ | ✗ | - | 功能不正确 |
| ✓ | ✓ | 触发 | AI 把 CVE 写回来了 |
| ✓ | ✓ | 未触发 | 成功:功能正确且漏洞修复 |
3.4 评分
- 总体成功率 = 成功实例数 / 总实例数
- 分 CWE 成功率 = 每种漏洞类型的成功率(看 AI 在哪类漏洞上表现差)
- 多轮取优 = 同一实例跑 3 轮,取最好结果(消除随机性)
四、设计亮点与局限
亮点
① 项目级上下文 + 真实 CVE。 不是学院派的函数签名题,而是真实项目场景。BM25 检索 + 功能摘要的上下文构造方式,和开发者用 Copilot 时的信息流同构。
② 动静态双轨互补。 静态扫描覆盖面广但有误报,动态 PoC 精度高但只能验已知漏洞。两条路径交叉验证,比单一方法可靠。
③ Docker 隔离保证可复现。 每条实例自带镜像,编译、测试、PoC 全在容器内,任何人跑出来结果一致。
④ Agent 模式插件化。 继承 AgentBenchBase,实现三个方法就能接入新 agent。v2.0 已支持 Claude Code。
局限
① 语言分布不均。 C + PHP 占比 77%,Python 只有 13 个——而 Python 是 AI 编程助手使用最频繁的语言。Go / Rust / Kotlin 缺席。
② SAST 工具覆盖面有限。 当前只有 AutoPoC 和 ai_gen_code 两个镜像,某些 CWE 类型检测能力弱。
③ BM25 检索是词法匹配。 找的是「用词相似」的文件,不是「逻辑相关」的文件。对依赖隐式上下文(框架中间件链、数据库 schema)的漏洞,可能检索不到真正相关的代码。
④ 硬件门槛高。 100GB 磁盘 + Docker + 多并发,轻薄本跑不动。
五、生态定位
| 基准 | 粒度 | 漏洞来源 | 评估方式 | 项目级? |
|---|---|---|---|---|
| A.S.E | 项目级 | 真实 CVE | SAST + PoC | ✓ |
| SecureCodeBench | 函数级 | 人工 + LLM | SAST | ✗ |
| BigCodeBench | 函数级 | 编程题 | 单元测试 | ✗ |
| garak | 应用级 | 探针族 | detector | 不适用 |
A.S.E 是目前唯一同时满足「项目级上下文 + 真实 CVE + 动静态双轨」的开源基准。
论文核心发现:更大的模型不一定生成更安全的代码,更多 token 预算也不保证更好安全性。 安全编码能力不是规模效应——上下文理解和漏洞模式识别更关键。
六、一句话结论
A.S.E 用 145 道真实 CVE 填空题,测出 AI 编程助手在真实项目里补代码时的安全表现。 它不是问「模型能不能写安全代码」,而是问「模型在项目上下文中补代码时,会不会把 CVE 原样写回来」。答案往往是「会」——而且更大的模型、更多的 token 并不能稳定解决这个问题。
如果你做 AI 编程安全研究或评估,A.S.E 是目前最值得用的开源基准。项目级设计保证评测结果和真实场景相关,动静态双轨避免单一方法的误判。