正在刊行长文 · Essay
2026-09-30所有内容
随机比特 · Random Bits

测试全绿,越权请求也成功:一个 AI 代码评审实验

2026-09-30AI Engineering / Systemsrbits.uk
测试全绿,越权请求也成功:一个 AI 代码评审实验

我在本地模拟了一份订单取消 PR。原有测试全绿。换成 Bob 去取消 Alice 的订单,函数却返回了 OK,订单状态变成“已取消”,库存释放计数也加了 1。

这是一段可复现的构造代码,不是线上事故,也不是某个智能体真实提交的 PR。它让评审者看清,当代码和测试一起生成,绿灯究竟守住了哪些规则。

未使用的操作者参数暴露越权缺陷

需求限定用户只能取消自己的订单,已发货订单不能取消;成功取消时才释放库存。模拟 PR 的核心实现只有几行。

function cancel(order, actorId) {
  if (order.status === 'shipped') return 'ALREADY_SHIPPED';
  order.inventoryReleased += 1;
  order.status = 'cancelled';
  return 'OK';
}

原测试只让 Alice 取消自己的未发货订单。它检查返回值、订单状态和库存计数,全部通过。代码里的已发货拦截也确实存在。若只沿着这条成功路径读,很容易把“分支写在代码里”当成“业务规则已有保障”。

但 actorId 从头到尾没有参与判断。我加了一条负向断言,要求 Bob 取消 Alice 的订单时返回 FORBIDDEN。这条断言失败了。实际返回 OK,还执行了取消和库存释放。这里发现的是原实现的缺陷,不是测试工具制造的故障。

这时不该批准合并。补上一条会失败的测试,只是把缺口照亮;所有权校验仍要在实现中修复,并再次运行测试。

原正向测试通过,但 Bob 取消 Alice 订单成功;补充越权断言后测试失败

单处分支变异检验测试敏感度

再看原实现中正确的已发货守卫。我在本地打开一个实验开关,临时跳过这条判断,其他逻辑不变。这一步由评审者主动完成,用来测试原有断言的敏感度;它不是模拟 PR 原本的缺陷。

守卫被跳过后,Alice 取消未发货订单的原测试仍然通过。这个输入本来就不会走已发货分支。随后我加入“已发货必须拒绝”的断言。它在原实现中通过,在跳过守卫的版本中失败。

跳过已发货守卫后,原正向测试仍通过;补充已发货拒绝断言能检出这一变异

变异测试要问的是,故意改变一处行为后,测试能否发现。Stryker 的官方说明介绍了自动化做法。这个实验只证明原正向测试漏掉了已发货拒绝路径,以及新增断言能检出这一次变异。它不能证明整段实现已经正确。

人工复核并发与跨系统边界

本地脚本把“库存释放”简化成内存里的计数加一。真实项目是否使用跨表事务、远程库存服务或消息重投,本实验都没有验证。

如果两个取消请求同时读到未取消状态,状态更新和库存释放由什么机制协调?如果库存已释放而订单状态写入失败,谁负责重试或补偿?已经取消的订单再收到请求,接口承诺什么结果?这些问题需要看存储条件、下游契约和故障处理,不能从一条单元测试的绿灯推出来。

下次评审一份附带测试的生成代码,先挑一条关键拒绝规则,临时让它失效,再运行现有测试。若测试仍绿,就请提交者补上能检出这次改动的断言;然后再细读实现与系统边界。

随机比特公众号二维码
公众号 · 随机比特
从 AI 工具热闹里拆工程真相

写边界、控制面、上下文、成本与安全。