安全考量
本页面向两类读者:集成方(用访问密钥调 GenAuth 的你的服务端)与资源侧(接受访问令牌的你的 API 或第三方服务适配层)。每个威胁一节,先讲攻击怎么发生,再给分级建议。
规范性用语分级:必须 / 不得——违反即产生可利用的安全缺口;应当 / 不应——强烈建议,偏离需有明确理由并自担风险;可以——可选加固。
威胁模型总览
Agent Identity 场景的攻击面,收敛为四类威胁:
| 威胁 | 一句话描述 | 首要防线 |
|---|---|---|
| 凭证窃取(Credential Theft) | 访问密钥或令牌被偷,攻击者冒充你的服务端或 Agent 行动 | 密钥保管硬约束 + 短有效期 + 熔断 |
| 混淆代理(Confused Deputy) | 权限更高的中间人(你的服务端 / Agent)被诱导替攻击者行使权限 | 委托对象来源钉死 + 资源侧完整校验 |
| 令牌重放(Token Replay) | 截获的令牌在有效期内被重复使用 | 传输加密 + aud 绑定 + 最短有效期 |
| 越权委托(Delegation Beyond Authority) | Agent 被委托了委托人本没有、或组织不允许的权限 | 最小 scope 纪律 + 权限交集 + 资源侧兜底 |
一条贯穿全页的设计原则:委托只能缩权,不能扩权——任何一层校验的缺席,都必须由其余层兜底,而不是假设上一层已经做对(纵深防御)。
凭证窃取
这套体系里有两类凭证,爆炸半径完全不同:
- 访问密钥(AK/SK):租户级长期凭证。泄露后攻击者可以以你的组织名义发起委托——这是最坏情况。
- 委托令牌 / 访问令牌:用户级短期凭证,天生短时、缩权、绑定单次委托。泄露的伤害被有效期和 scope 双重限制。
因此安全投入的重心不对称:密钥按堡垒标准保管,令牌靠短有效期和最小 scope 自限。围绕访问密钥的完整要求见下一节;围绕令牌的要求分散在令牌重放与 audience 绑定两节。
组织级授权确认(服务端受信集成)的硬约束清单
组织级授权确认(详见 Consent 与审批)允许你的服务端持访问密钥、在没有终端用户实时点击的情况下为用户发起委托。该路径等同于以组织名义授权,访问密钥泄露即组织级风险,务必按本清单加固。
先想清楚再用这条路径
这条路径的信任前提是"你的服务端本身是受信的"。如果你的调用方是浏览器、移动端、或任何最终用户可触达的环境,不得走此路径——改用用户级授权确认(interactive)流程。
逐条硬约束:
- 访问密钥的保管——必须将 AK/SK 存放于密钥管理系统(KMS / secret manager)并按环境隔离;不得写入代码库、前端资源、移动端包体、日志或错误信息;应当定期轮换,并在人员变动、疑似泄露时立即轮换(轮换操作见吊销与应急处置)。
- 网络边界——应当将发起组织级委托的出口收敛到固定的服务端网段,并在你的网络层配置 IP 允许列表或走私网/专线;不得从公网不受控环境(CI 日志可见的临时容器、开发者本机长期持有等)直接调用。
- 最小 scope——必须按任务申请最小 scope 集合(如
webagent.web_search:run),不得以do_anything类宽能力或全量 bundle 兜底"以后可能用到"的权限。 - 短期限——应当把
expiresIn设为完成该任务所需的最短时长;不应默认取有效期上限。 - 专用 Agent 标识——必须为每个服务端集成场景使用专用的 Agent 标识;不得多个业务线共享同一个 Agent,否则审计无法归因、熔断无法定点。
- 审计与告警——应当对签发量突增、非常用 scope 出现、非常用用户面扩大建立告警,并以
audit_id/grant_id留存全链路记录(见审计与合规报告)。
混淆代理(Confused Deputy)
经典形态:攻击者自己没有权限,但能让权限更高的中间人替他做事。在委托体系里,"中间人"就是你的服务端或 Agent——攻击者不偷凭证,而是操纵委托的参数。
最典型的入口是委托对象被替换:如果"为哪个用户发起委托"这个值来自客户端可控的输入,攻击者把 usr_alice 换成 usr_ceo,你的服务端就用自己的合法密钥、以受害者的名义签出了委托令牌。
集成方的防御:
- 必须把委托对象(用户 id)的来源钉死在服务端会话或可信身份上下文;不得直接采用请求参数、URL query、前端表单中的用户标识。
- 必须校验 interactive 流程回调中的
state参数与发起时一致,防止授权结果被嫁接到别人的会话。
双轨兼容期风险
SDK(@eazo/anima v0.2.1)已弃用顶层 userId 参数(改为 user: { id }),但服务端在兼容期内仍接受旧参数。这意味着:即使你的新代码全部用了新形状,一段被遗忘的旧代码、或一个直接拼 HTTP 请求的旁路调用,仍然能以旧参数指定任意委托对象。兼容期内,应当在你的出口层(网关/中间件)扫描并拦截携带顶层 userId 的出站请求,把旧形状当成缺陷处理而非风格问题。字段契约详见 Token 与 Claim 参考。
资源侧的防御(纵深防御的最后一层):
- 必须校验访问令牌的
aud与自己匹配(详见 audience 绑定)。 - 应当识别
act结构(判断act.type === 'eak_delegation'),把"Agent 代表用户"与"用户本人"区分对待,对 Agent 通道施加更严格的操作白名单。 - 不得仅凭
sub(委托人)放行——只认sub意味着 Agent 拿到的缩权令牌与用户本人的全权访问无法区分,缩权在你这一侧直接失效。act与scope的完整字段说明见 Token 与 Claim 参考。
令牌重放
截获的令牌在有效期内可以被重复使用——防御方向是压缩"截获"与"可用窗口"两头:
- 必须全链路使用 TLS(HTTPS)传输令牌;不得将令牌置于 URL query、日志、错误信息或前端可见位置。
- 必须校验令牌有效期与签名;应当在关键路径调用令牌校验(introspection)做在线核验。
- 应当把令牌有效期设为最短可用值——有效期越短,重放窗口越小。委托令牌在有效期内以自然过期为主要失效方式,应急收权走密钥级与授权级的分层处置,见吊销与应急处置。
- interactive 流程中的授权码为一次性设计,不得在集成侧缓存或重试重用。
越权委托
"不能委托你没有的权限"是这套体系的底线原则:一次委托的权限上界 = 请求的 scope ∩ 委托人真实权限 ∩ 组织策略允许(三方交集,概念与发布状态详见 Delegate Token 与缩权)。
工程上的对应要求:
- 集成方必须只为委托人真实拥有、且当前任务真实需要的权限申请 scope——把交集原则前置到申请侧,而不是指望校验侧兜底。
- 组织应当在凭证与 Agent 维度维护明确的允许清单(哪个密钥可以为哪些 Agent 申请哪些 scope),并避免"空清单等于放行一切"式的默认配置。
- 资源侧必须按令牌中的
scope做操作级鉴权,不得把"令牌有效"等同于"全部操作可做"。
Audience 绑定与令牌透传禁止
两种令牌各有明确的受众(audience),错用即是漏洞:
- 委托令牌的
aud面向 GenAuth 令牌兑换——它是"授权凭据",不是"访问凭据"。集成方与 Agent 不得把委托令牌直接当作资源访问凭证发给任何资源服务;资源侧不得接受它。 - 访问令牌绑定单一目标资源。资源侧必须校验
aud与自身一致,不得接受为其他资源签发的令牌。
令牌透传(token passthrough)明令禁止:任何服务不得把收到的令牌原样转发给下游服务使用。透传会让下游拿到一个 aud 不属于它的令牌,审计链在这一跳断裂、缩权边界失效。正确做法是:需要访问下游时,回到 GenAuth 为目标资源做一次新的令牌兑换。字段口径见 Token 与 Claim 参考。
组织性防线:责任人与一键熔断
以上都是技术防线。两道组织性防线决定了"出事那一刻"的响应速度:
- 责任人在册——组织必须为每个 Agent 指定技术负责人(Owner)与业务归属人(Sponsor),不得允许无主 Agent 存续;人员变动时归属自动接续。没有责任人,告警响不响都没人接。身份模型详见 Agent 的身份模型。
- 一键熔断(Kill Switch)——应当预先演练分层收权路径:单次授权吊销 → Agent 级熔断 → 密钥级吊销,明确每一层的生效时效与操作人。事发时不是查文档的时候。操作矩阵详见吊销与应急处置。
下一步
- Delegate Token 与缩权 —— 交集公式与"每跳只收窄"的机制细节
- 吊销与应急处置 —— 分层吊销矩阵与各层生效时效
- Token 与 Claim 参考 ——
aud/act/scope的完整字段契约