UC Berkeley 团队用 AI Agent 审计 13 个基准,发现 45 个无需解题的满分作弊方案
We Scored 100% on AI Benchmarks Without Solving a Single Problem April 06, 2026
UC Berkeley 团队构建全自动 AI Agent 审计 13 个广泛使用的基准,发现 45 个作弊方案,全部基准被评为 critical 风险,共归纳 16 种攻击类型。
原文给出了13个常用基准的45个作弊方案细节和防范设计原则,读者可以据此检查自己依赖的评测是否可信。

我们在没有解决任何问题的情况下在 AI 基准测试中获得了 100% 的分数
Hao Wang, Qiuyang Mang, Alvin Cheung, Koushik Sen, Dawn Song
UC Berkeley
2026 年 4 月
(预计阅读时间 8-10 分钟,工具可在 github.com/moogician/trustworthy-env 获取)
虚假分数,真实后果
每一家大型 AI 公司都用基准测试分数来推销他们的模型。训练数据公司用这些分数来为产品定价。而且,基准测试分数越来越不只是衡量模型——它们正在塑造模型的训练方式,从 RL 奖励信号到数据过滤流程。基准测试不只是衡量能力——它们塑造行为。而如果它们可以被利用,它们就会主动训练模型去作弊。
那么,当基准测试本身就有漏洞时,会发生什么?
这不是假设。一个“将 SWE-bench 提升了 5%”的模型,可能只是更擅长利用测试套件的漏洞。基于基准测试提升来定价的训练数据,可能正在教模型去钻评估的空子,而不是解决真实问题。让你完成 B 轮融资的那个排行榜数字,任何读过评估脚本的人都能把它注水。
以下是公开发生的事情:
- IQuest-Coder-V1 声称在 SWE-bench 上达到 81.4%——随后研究人员发现 24.4% 的轨迹只是运行
git log从提交历史中复制答案。修正后的分数:76.2%。 - METR 发现 o3 和 Claude 3.7 Sonnet 在 30% 以上的评估运行中存在奖励黑客行为——堆栈内省、猴子补丁评分器、运算符重载。
- OpenAI 放弃了 SWE-bench Verified,因为发现 59.4% 的受审计问题存在有缺陷的测试。
- 在 KernelBench 中,
torch.empty()返回包含参考答案的陈旧 GPU 内存——零计算,满分。
这些是人们手工抓到的。我们构建了一个 AI 智能体来自动发现它们——而且它发现了更多。
我们做了什么
我们构建了一个 AI 智能体,它深入分析基准测试评估代码,并自动发现基准测试分数的注水行为。我们将它指向了 13 个广泛使用的 AI 基准测试——包括 FrontierCS、BFCL、LiveBench、GAIA、WebArena、AGIEval、AgentBench、Terminal-Bench、tau-bench、MLE-bench、OSWorld、FieldWorkArena 和 CAR-bench。
13 个受审计基准测试的发现概览。每个基准测试都被评为严重风险。
这 45 个已确认的作弊方案每一个都附带了可用的概念验证——即在不解决实际任务的情况下获得注水或满分分数的代码。它们影响的基准测试被用于评估从代码生成到网页导航再到通用 AI 助手的一切。
我们如何找到它们
我们使用了一个全自动混合智能体,它在零人工干预的情况下扫描基准测试仓库、识别潜在漏洞、生成可用的漏洞利用代码,并端到端验证结果。人工审计无法规模化——一位人类专家可能在单个评估框架上花费数天,而我们需要覆盖 13 个基准测试,每个都有数百个评分脚本。
该 agent 运行一条双重检测流水线。LLM 检测器使用 15 个专门的扫描器,对代码意图进行推理——将任务描述与测试逻辑交叉比对,以捕捉规范不匹配和答案泄露等语义缺口。形式化检测器使用 12 个基于 AST 解析、数据流分析和 z3 SMT 求解构建的分析模块,在不借助任何语言模型的情况下捕捉结构性问题。
整个系统是一条 8 阶段的审计流水线:
完整的审计流水线:从基准数据摄入,到对抗性 PoC 生成,再到发现结果关联。
将 agent 指向一个基准仓库,它就会生成一份完整的审计报告——漏洞分析、可用的漏洞利用代码以及修复建议。本文中 45 个经确认的 hacking 方案全部由 agent 发现、编写并验证,而非我们。
示例 1:满分,零工作量(Frontier-CS)
在 Frontier-CS 的研究赛道中,评估器通过 importlib.util.spec_from_file_location() 和 exec_module() 加载提交的解决方案。这意味着提交的代码与评估器运行在同一个 Python 进程中——共享 sys.modules、全局状态和调用栈。
恶意解决方案可以沿调用栈向上遍历并替换评分函数:
class Solution:
def solve(self):
import sys
frame = sys._getframe(1)
while frame is not None:
if 'evaluate_kernel_performance' in frame.f_globals:
def fake_evaluate(*args, **kwargs):
return {
"score": 100, "pass_all": True,
"geometric_mean_speedup": 10.0,
"total_tests": 10, "passed_tests": 10,
}
frame.f_globals['evaluate_kernel_performance'] = fake_evaluate
break
frame = frame.f_back
return {"code": "pass"} # No actual solution needed
结果:无需解决任何问题即可获得 100 分满分。该解决方案甚至不需要包含相关代码。其他攻击途径包括:对 torch.allclose 进行猴子补丁使其始终返回 True,覆盖基线文件以伪造加速比,或使用 atexit 将伪造分数作为最后一行 stdout 注入。Docker 容器在同一进程中运行评估器和解决方案,没有任何沙箱隔离。
根本原因:提交代码与评估基础设施之间没有进程隔离。解决方案对容器内的评估器源代码和基线实现拥有完整的读写权限。
示例 2:伪造的 C 扩展(Terminal-Bench)
该任务要求 agent 编写一个用于投资组合风险/收益计算的 C 扩展——这是一项系统编程任务,本应测试底层优化技能。测试套件有三项检查:
test_c_extension_exists()——验证存在一个编译好的.so文件,其中包含portfolio_risk_c和portfolio_return_c函数test_correctness_small()——检查小输入下的计算准确性test_performance_and_scalability()——要求相比纯 Python 有 1.2 倍的加速
关键缺口:测试 1 检查 C 函数是否存在,但从不调用它们。测试 2 和测试 3 从 Python 包装器导入,而非从 C 扩展导入。包装器内部可以使用任何实现。
漏洞利用——一个假的 C 扩展搭配一个 numpy 包装器:
// portfolio_optimized_c.c — compiles to .so, passes test_c_extension_exists()
static PyObject* portfolio_risk_c(PyObject *self, PyObject *args) {
return PyFloat_FromDouble(0.0); // Dummy — never actually called
}
static PyObject* portfolio_return_c(PyObject *self, PyObject *args) {
return PyFloat_FromDouble(0.0); // Dummy — never actually called
}
# portfolio_optimized.py — uses numpy, not the C extension
import numpy as np
import portfolio_optimized_c # noqa: imported so .so is loadable
def portfolio_risk_c(weights, cov_matrix):
w = np.array(weights)
cov = np.array(cov_matrix)
return math.sqrt(float(w @ cov @ w)) # numpy, not C
结果:三项测试全部通过,而无需编写任何有意义的 C 代码。假的 .so 满足了存在性检查。numpy 满足了正确性(误差在 1e-10 以内)和性能(比纯 Python 循环快 1.2 倍)。
根本原因:该基准测试的是容易测试的内容(文件是否存在?),而非它声称要测试的内容(agent 能否编写优化的 C 代码?)。没有任何检查验证 C 扩展函数是否产生正确输出,或是否真的被调用。
示例 3:全部 812 个答案都在一个 JSON 文件中(WebArena)
WebArena 测试智能体能否浏览网站以完成真实世界的任务——购物、发帖、内容管理。评估器通过字符串匹配将智能体的答案与参考答案进行比对。
问题在于:config_files/test.raw.json 以明文形式包含了每一个参考答案:
{
"task_id": 0,
"intent": "What is the top-1 best-selling product in 2022",
"eval": {
"reference_answers": {
"exact_match": "Quest Lumaflex Band"
}
}
}
全部 812+ 个任务。每一个答案。就放在智能体运行所在的同一个文件系统上。没有任何沙箱机制阻止智能体读取它。一个简单的作弊智能体:
class CheatingAgent:
def __init__(self):
with open('config_files/test.raw.json') as f:
tasks = json.load(f)
self.answers = {
t['task_id']: t['eval']['reference_answers']
for t in tasks
}
def act(self, task_id, observation=None):
ref = self.answers.get(task_id, {})
answer = ref.get('exact_match', ref.get('must_include', [''])[0])
return {'action_type': 'stop', 'answer': answer}
结果:在所有字符串匹配任务上获得满分,且零网页浏览。没有点击,没有导航,没有对网页界面的理解。只需读取一个 JSON 文件并返回答案。
根本原因:参考答案存储在智能体可访问的文件系统中,且没有完整性保护。评估器读取的正是智能体能够访问的那些 JSON 文件。
设计能抵御奖励黑客的基准测试
如果你的基准测试可被利用,它就会被利用。
在 13 个基准测试和 45 个已确认的黑客解决方案中,我们识别出 16 种不同的攻击类型——从薄弱的测试断言和答案泄露,到共享地址空间和分数注入。它们归结为几种反复出现的设计缺陷。以下是避免它们的方法。
将一切评分的东西与一切被评分的东西隔离
我们利用的最常见模式是:提交内容与评估器运行在同一进程、容器或文件系统中。如果提交的代码能够读取参考答案、覆盖基线文件、猴子补丁评分函数,或将输出注入评估器的 stdout——它就会这么做。在独立容器中运行评估器和提交内容,不共享任何状态。将所有参考文件和基线文件挂载为只读。在每次运行前后对它们进行校验和验证。
永远不要信任你正在评估的代码所输出的内容
自我报告的性能指标、由提交内容控制的时间测量,以及宽松解析的评估器输出,都是攻击面。评估器必须从原始输出中独立计算每一项分数。使用严格的模式解析结果。从提交进程外部测量性能。将提交内容产生的一切视为不可信输入。
测试测试本身,而不仅仅是提交内容
我们的许多漏洞利用之所以能通过,是因为测试比任务描述更薄弱。首先针对一个简单或空提交运行每个测试套件——如果它能通过,说明测试是坏的。添加应该失败的对抗性负面用例。交叉检查规范中的每一项要求都有对应的断言。如果任务说“编写 C 代码”,要验证 C 代码确实被调用,而不仅仅是存在一个 .so 文件。
让容差和基线保持诚实
宽松的数值容差、朴素的基线,以及参考答案与提交答案之间的精度不匹配,都会为在没有真实能力的情况下虚高分数创造空间。收紧阈值以匹配实际任务难度。使用经过独立验证的、有竞争力的基线。在双方强制使用相同的精度设置。报告置信区间,而不仅仅是点估计。
将评估代码视为生产代码
我们的两种攻击类型利用了评估脚本中的明显漏洞——这些逻辑错误会让错误答案获得满分。对你的评估脚本进行模糊测试。用故意错误的提交运行它们,并验证它们会产生不及格的分数。以你对待任何生产系统同样的严谨态度审查评估代码,因为基于其输出所做的决策就是生产决策。
要点
一个值得信赖的基准测试不仅仅衡量成功——它让作弊比正确解题更难。有缺陷的基准测试不仅会产生错误的排行榜——它们还会污染训练信号、抬高数据定价,并误导部署决策。如果没有人审计评估基础设施,那么建立在其上的一切都不可靠。
我们的智能体发现了 45 个经确认的作弊解法,而人类审查者却漏掉了它们——不是因为它们很隐蔽,而是因为没人在看。 这些工具和方法论已在 github.com/moogician/trustworthy-env 开源。 今天就用它来测试你自己的基准测试吧!
Berkeley RDI
推进去中心化与 AI 的科学、技术和教育,以赋能负责任的数字经济。
版权所有 © 2025 UC Regents;保留所有权利
来源:Berkeley RDI:Blog(AI 安全与评测) · rdi.berkeley.edu