Gateway API Key 的明文存储与非恒定时间比对¶
证据等级:F(源码直接证明)
分析基线:4f843556
一句话¶
Gateway API Key 验证优先使用明文比对,回退到 SHA256 哈希。两者均使用 Python == 而非恒定时间比较。SHA256 无盐。注释将安全回归标记为"progress"。
1. 验证路径:明文优先¶
backend/app/api/gateway.py:45-48:
# First try plaintext (new behavior)
result = await db.execute(
select(Agent).where(
Agent.api_key_hash == api_key, # ← 明文直接比对
验证先尝试明文匹配,失败后才回退到哈希。注释称明文为"new behavior"——即未来计划删除哈希回退,全部改为明文存储。
2. 非恒定时间比对¶
门关(gateway)使用 Python 的 == 操作符来比对 API Key:
Python 的 == 在字符串比较时会在第一个不匹配字符处提前返回,比较时间与密钥前缀匹配长度成正比。攻击者可以通过计时攻击逐步猜测 key 的前缀。
对比:WhatsApp 和 Slack 的 webhook 验证使用 hmac.compare_digest——恒定时间比较。
3. 哈希无盐¶
SHA256 无盐。如果迁移到明文存储完成,数据库泄露即全泄露。即使保留哈希,无盐意味着相同的 key 产生相同的哈希,攻击者可以批量比对。
4. 注释用词¶
注释将"明文存储"称为"new behavior"和"progress",将"哈希存储"称为"legacy"。这暗示项目的安全方向是从哈希到明文——与行业最佳实践相反。
5. 与 AI Coding 的关系¶
- 注释反映 prompt 意图:开发者(或 AI)被要求"添加明文比对作为新行为"——AI 忠实地执行了,并加上了注释标记状态
- 无安全意识:AI 不会主动说"明文存储 API Key 是安全风险,不应标记为 progress"——这需要安全判断
- 非恒定时间比对:
==是 Python 中最自然的字符串比较方式——AI 不会主动选择hmac.compare_digest,除非 prompt 明确要求 - WhatsApp/Slack 的
hmac.compare_digest是另一个开发者/任务的结果——同一个安全属性在不同模块中实现不一致
6. 关联¶
- 010 · Gateway API Key:新旧逻辑并存:创建和验证逻辑不一致(迁移半成品)