设计企业 Agent 权限时,先把两句话写在白板上:“它是谁?”和“它现在能做什么?”这两个问题混在一起,证书部署得再整齐,也可能把一个身份合法的客服 Agent 变成财务接口的代理人。
10 月 19 日,微软在《Securing the agentic insider》中把企业内部 Agent 也纳入安全边界讨论。这里真正值得产品团队吸收的,是把身份、权限、数据、网络和运行时一起考虑,而不是把某个安全产品的宣传直接当作自己的防护能力。微软原文
证书解决的是哪一段问题
SPIFFE 的 SVID 是工作负载证明身份的凭据,X.509-SVID 可以用于建立经过身份校验的 TLS 连接。SPIFFE 的概念文档也说明,工作负载之间的隔离强度不在规范本身的保障范围内。因此,“用了 SPIFFE”不能推导出“提示词注入无效”。SPIFFE 概念
我会把链路拆为三层。第一层验证证书链、信任域和具体工作负载身份;第二层从受信的业务会话取出租户、用户和资源范围;第三层按动作授权。低权限 Agent 即使获得有效证书,也不应自动获得导出客户表、发送邮件或发起付款的权限。
图中 mTLS identity 后面仍有 Policy check。tenant、action、resource 必须由代理层验证,不能让模型自己填写一个 tenant_id 就获得对应租户的数据。拒绝分支要终止调用,不能以“先试一下接口是否允许”代替裁决。
一个可以单独验证的授权边界
下面只演示策略裁决,不实现 TLS 握手。示例中的身份来自测试夹具;真实系统必须用已经完成证书验证的连接信息填入它。授权失败返回 False,调用层据此停止。
def allowed(identity, session_tenant, action, resource_tenant): known = {"spiffe://example.test/agent/support"} return (identity in known and session_tenant in {"tenant-a", "tenant-b"} and session_tenant == resource_tenant and action == "order.read") who = "spiffe://example.test/agent/support" assert allowed(who, "tenant-a", "order.read", "tenant-a") assert not allowed(who, "tenant-a", "order.read", "tenant-b") assert not allowed(who, "tenant-a", "payment.create", "tenant-a") assert not allowed(who, "unknown", "order.read", "unknown") print("4 authorization boundaries passed")四个断言分别覆盖同租户只读成功、跨租户失败、高风险动作失败和未登记租户失败。将动作或资源改成未登记值时也应该默认拒绝。它验证的是策略函数的行为,没有验证 SPIRE、网关、数据库行级权限或证书轮换。
交付时需要留下的证据
| 边界 | 应验证的反例 | 需要保存的结果 |
|---|---|---|
| 身份 | 错误信任域、过期证书 | 握手拒绝记录 |
| 租户 | A租户请求B租户资源 | 策略拒绝与资源标识 |
| 动作 | 查询身份尝试导出或付款 | 工具未执行的证据 |
| 生命周期 | 用户撤权后重用旧会话 | 权限失效时间与缓存行为 |
10 月 23 日 OpenAI 公开的训练环境隔离说明再次强调纵深防御,也明确该研究环境与已发布产品的客户使用环境不同。它对这里的启发是把“边界失效后还有什么阻断”列入设计评审,而不是把研究案例套成某个业务系统的事故结论。OpenAI 原文
我愿意对客户承诺的是可观察、可复测的授权链路。至于“永不失守”,证书和一段策略代码都不足以支撑这个说法。