基于 arXiv:2608.17485 论文实现的形式化验证工具,检测 LLM Relay 在多租户场景下是否满足 KeyPooling defense contract,确保各 tenant 的 cache 严格隔离不串读。
一个用于验证 arXiv:2608.17485(KeyPooling)防御合同是否被遵守的工具:在一个多租户 relay 中,没有人能读取到其他租户写入的缓存。
在服务于多个租户、共享单一上游凭证的 LLM relay 中,缓存域可能会发生塌陷:两个不同的租户最终共享了同一个缓存命名空间。其结果是信息泄露——租户 B 在不知情且未经许可的情况下读取了租户 A 写入的内容。
KeyPooling 论文(arXiv:2608.17485)定义了防御合同:
「从认证身份派生的命名空间,必须在每次最终缓存查询和写入时保持不变」
也就是说:租户的认证身份必须派生出一个命名空间,在每次缓存 lookup 和写入时都持续存在。如果 relay 没有发送命名空间(将其塌陷了),合同就被打破了。
对 mock 网关执行论文中的正式 E2 测试单元,并给出合同裁定:
collapse 模式:单一共享域 → 应该失败(exit 1)。
isolate 模式:每个租户从 bearer 派生的命名空间 → 应该通过(exit 0)。
裁定基于真实身份,而非测试单元的标签。只要读取的 cached_tokens > 0,且写入者(hit_writer)与读取者不是同一租户,即为泄露。这使得裁定对执行顺序具有不变性,包括对抗性排列(其他租户的 cross 单元在 cold/owner 之前执行)。
keybound audit --fixture collapse
# fixture: collapse | verdict: FAIL | defense_contract: not_satisfied
# cause: 1 dominio(s); cross_con_leak=['A1-cold-prime', 'A2-owner-hot']
报告从不包含租户密钥或收到的 Authorization——只有标识符(租户 A/B,prompt P/R)和有效的域。
验证方式(三方治理)
开发遵循了内部协议:实现 → 在干净克隆中独立审计 → merge 审批。过程中捕获并修复了三个真实 bug:
mock 中按字符(而非按词)匹配前缀 → 缓存误报。改用完整词比较修复。
cached_tokens 负值未校验 → 可能用荒谬值给出 PASS。改用类型/范围校验(CellError)修复。
按 kind=="cross" 裁定 → 如果 cross 单元先执行会产生假阴性。改用真实身份路径(hit_writer)修复,由审计发现,非自报告。
测试针对合成 mock 网关运行(无网络、确定性),而非真实的 LiteLLM——快速套件验证审计器逻辑,不在每次 CI 中重新确认漏洞。真实漏洞记录在 RESEARCH.md / KNOWN_ISSUES.md 中,并通过 NewAPI 适配器验证(v0.3 roadmap)。
46 个测试通过,ruff 干净,覆盖率 90%(审计核心 97–100%)。
裁定对任意测试单元顺序具有不变性,包括对抗性顺序。
git clone https://github.com/amurlaniakea/keybound
cd keybound
python -m venv .venv && source .venv/bin/activate
pip install -e .
keybound audit --fixture collapse # 预期 FAIL
keybound audit --fixture isolate # 预期 PASS
Repo: https://github.com/amurlaniakea/keybound
Paper: KeyPooling (arXiv:2608.17485)
License: AGPL-3.0-or-later — Copyright 2026 Pedro Sordo Martínez