Skip to content

IR-0006 AC-9 SEV:HIGH — wave_schema wallclock_sec/wall_sec 键名不匹配→KeyError→cost-check fail-open 绕过(BEH-07 预算硬停失效) #470

Description

@randypanding

背景(独立验收发现)

IR-0006 验收阶段(#402 / 卡 #414 W2-C3),独立对 wave_schema.py
BEH-07 预算硬停做代码级复算时发现:任何在卡 budget 块中声明 wallclock_sec 维度的卡,
当 wave_check 对账时,Python 直接抛未处理的 KeyError 异常退出码 1,
被 cost-check.sh 当作"非 INFRA、非超限"吞掉,最终输出 WAVE-OK = 预算硬停机制被静默绕过

Bug 链(完整 fail-open 路径)

第 1 层:键名不一致(wave_schema.py L168 vs L191)

  • BUDGET_KEYS 声明(L54):('usd', 'tokens', 'wallclock_sec', 'human_minutes')
    ← wallclock_sec(与 card.yml 模板一致)
  • ledger 聚合 agg 键(L168/L187-189):'wall_sec'
    ← wall_sec(与 standards/evidence/record.schema.yaml cost.wall_sec 一致)
  • 超限比较(L191-192)遍历 BUDGET_KEYS[:3],当 k=wallclock_sec 时
    agg['wallclock_sec'] = KeyError(agg 里只有 wall_sec)

第 2 层:异常未被 Python 代码捕获

KeyError 不是 die(3/4),是裸异常 → exit code = 1。

第 3 层:cost-check.sh 错误处理缺口(L230-249)

rc=1(未处理异常)时,rc 既非 2 也非 4,掉落到解析空 out → rows=[] → no error → no exceeded →
输出 "WAVE-OK 预算卡 0 张对账无 hard-stop 超限"。

净结果: 任何声明了 wallclock_sec 预算的卡,在真实超限场景下,100% 不会触发
BEH-07 的熔断三件套(熔断变量 + 撤 auto-merge + P0 issue)。预算硬停死。

实测复现(独立 agent 沙箱,非 CI 快照摆拍)

账本: 卡 #414 累计 wall_sec=8000s, usd=5.5, tokens=210k
预算: wallclock_sec: 7200(卡侧写的是 wallclock_sec——模板默认)
预期: exceeded_dims 至少含 wallclock_sec → on_exceed=hard-stop → exit 4
实际: KeyError(wallclock_sec) → cost-check 打出 WAVE-OK → 绿

违反的治理条款

条款 影响
AC-9 BEH-07 波次预算硬停(四元组超限→熔断三件套) wallclock_sec 维度失效;同时超多维时列表推导提前崩,所有维度都不比较
宪法 §5 / INV-01 fail-closed 本该红的判定(超预算)被当作绿——违反 fail-closed 基本方向
ADR-0040 无人值守护栏 (b) auto-fix-limit 前的 cost-check 守卫失效——超限不会撤 automerge

修复建议(最小变更,不重写)

建议 A + C 合入(双保险):

方案 A(对账侧:键名映射)

# governance/wave_schema.py L191 附近
AGG_KEY_FOR_BUDGET = {"usd": "usd", "tokens": "tokens",
                      "wallclock_sec": "wall_sec",  # 关键映射
                      "human_minutes": None}
exceeded_dims = [k for k in BUDGET_KEYS[:3]
                 if k in budget and AGG_KEY_FOR_BUDGET[k] is not None
                    and agg[AGG_KEY_FOR_BUDGET[k]] > float(budget[k])]

方案 C(调用侧:硬兜底防御——任何非 0/4 exit code 都 INFRA)

# governance/cost-check.sh L230 附近
out=$(python3 DIR/wave_schema.py wave-check --cards cards --ledger-dir led 2>/dev/null) || rc=$?
if [[ -n "${rc:-}" && $rc -ne 4 ]]; then  # rc=4=超限(期望红),其余=异常→INFRA
  printf 'INFRA\twave-check 异常退出 rc=%d(fail-closed:预算面不可信,不静默通过)\n' "$rc"
  return 0
fi

C 兜底保证:未来任何类似命名错,至少不会 fail-open。

严重性自评

  • Severity: HIGH(治理核心 fail-closed 方向被违反,预算熔断承诺失效)
  • 可利用性: 中等(budget 模板占位明确写了 wallclock_sec: 7200,新卡 99% 会带)
  • 爆炸半径: 单仓 governance/cost-check.sh + governance/wave_schema.py(C1 路径)
  • 修复后回归: governance/tests 补一条 wallclock_sec 超限 wave-check rc=4 断言

验收对账基准(修完必须实测绿)

  1. 声明 wallclock_sec=7200,账本超 8000s → wave-check rc=4
  2. cost-check 同场景 → 打出 WAVE-EXCEEDED(非 WAVE-OK)
  3. 反向:未超限 → rc=0
  4. 畸形 budget(wallclock_sec 写成 wall_sec)→ validate 报错(保持模板对齐)

关联

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0P0 级严重漏洞bugSomething isn't workinggovernance治理体系相关security

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions