一轮评测说“最多查询两次”,这两次究竟指什么?生成了两个候选提示、经过了两次权限判断,还是工具真正执行了两次?三种口径会得出不同的成本,也会掩盖不同的权限问题。
10月9日Anthropic公开了评测和内部使用中发现的非预期行为,并表示将无实时互联网访问的范围扩展到其内部评测。报告公开时间与行为实际发生时间需要区分;本文采用的是这项调查提出的环境问题,不据此推算其他系统的事故率。原始调查
要让回放可解释,可以先拆出两本账:一份记策略决定,另一份记实际调用。被权限层拒绝的动作应留下记录,但不能算成目标工具已经被查询。
先用没有外网的假工具验证账本
下面的教学回放器只有一个本地字典工具。remote_submit只是一个会被拒绝的动作名称,不对应任何真实端点。它不发送请求、不读取凭证,也不执行模型提供的代码。
from collections import Counter def replay(actions, limit): if limit < 0: raise ValueError("negative query budget") local_data = {"manual": "approved local fixture"} events = [] calls = 0 for tool in actions: if tool != "local_lookup": events.append((tool, "denied")) continue if calls >= limit: events.append((tool, "exhausted")) continue calls += 1 result = local_data["manual"] events.append((tool, "observed", result)) return calls, events calls, events = replay( ["remote_submit", "local_lookup", "local_lookup", "local_lookup"], 2, ) counts = Counter(event[1] for event in events) assert calls == 2 assert counts == {"denied": 1, "observed": 2, "exhausted": 1} assert replay(["local_lookup"], 0)[0] == 0 assert replay([], 2) == (0, []) print("budget checks passed")四个候选动作里,只有两次本地查询真正发生。拒绝和耗尽都没有吞掉,它们是不同的终态。这里没有模拟攻破模型,也没有用几个敏感词去判断一次攻击是否成功,因此不能从输出换算越狱成功率或“攻破所需查询数”。
应用分支不是网络隔离
这段代码只证明自己的分支不会调用网络。它没有能力阻止同一Python进程的其他代码使用socket,也没有阻止子进程启动浏览器。把它命名为Sandbox,并不会增加这些约束。
真正的执行环境应另外限制网络出口、文件挂载和进程权限。需要测试的不仅是工具函数返回“拒绝”,还包括DNS、HTTP、浏览器、子进程是否存在其他通路。环境策略与应用策略要分别检查,失败记录也要保留。本文没有部署容器或验证系统级网络封锁,不把本地字典回放描述成完整安全沙箱。
回放记录应允许“没有拿到结果”
如果一次已授权调用超时,是否已经发生服务端工作,不能靠客户端猜测。能观察到调用但拿不到结果时,要保留调用身份与未知结果;重试则记为新的尝试。把超时重新放回队列,却仍只算一次,会把资源开销算小,也可能重复执行有副作用的动作。
SWE-bench指南同样区分结果报告与执行日志:评测框架没有崩溃,不意味着每个任务都被有效评分。这个区分可以借来检查自己的回放系统,但不能照抄某个计数字段后就宣称统计完全等价。评测结果说明
一份有用的回放报告,应该让复核者看见候选、拒绝、预算耗尽、真正调用及结果缺失。它可能没有一个漂亮的“防御硬度分数”,却能准确说明下一次该补哪一层实验。
本地核验:将上方代码保存为example.py,在 Python 3.9.6、仅标准库的临时目录执行python3 example.py,退出码为 0,输出budget checks passed。这验证了教学示例中的断言,不代表模型、GPU或线上系统实测。
示例只在本地合成动作上验证计数;没有对真实模型、网站或生产服务进行红队测试。