AI 运行监控与事件响应
提示注入检测器试图判断一段自然语言有没有恶意意图,生产系统最终要处理的却是可观察事实:谁读取了什么数据,哪项策略允许了哪个动作,外部系统发生了什么变化。AI 运行检测应围绕权限转换、跨域数据流和现实副作用建模。 模型意图难以稳定观测,这些状态转换可以由执行组件记录、阻断和核验。
一串具有相同 run_id 的日志只能说明事件一起发生。要回答“哪份外部文档影响了这次跨用户查询”和“这次查询又导致了哪次外发”,还需要把输入、上下文、模型调用、策略决定、工具结果和副作用连接成带方向的 Run Causal Graph。事件响应沿同一张图隔离后继动作、撤销仍有效的能力,并确认已经发生的现实影响。
攻击链在单点日志里看起来都很正常
设想客服 Agent 可以解析售后附件、查询当前用户订单并发送回复。攻击者能制作附件并发起普通售后请求,没有其他客户的身份、订单 API 凭证和邮件服务权限。他在 PDF 隐藏层写入指令,要求读取高价值订单并把摘要发送到外部地址。
完整路径跨过多个组件:
- 上传网关接收 PDF,解析器提取隐藏文字,却只记录“解析成功”。
- 上下文组装器把附件片段交给模型,没有保留外部来源和敏感标签。
- 模型提出订单查询,订单网关看到客服服务账号并放行跨用户读取。
- 工具返回订单内容,Agent 把结果继续放入上下文。
- 模型提出邮件发送,策略只检查 Agent 是否拥有邮件工具,没有检查数据来源与目的地。
- 邮件服务成功投递,Agent 日志只记录工具返回
200。 - 攻击内容或错误摘要被写入长期记忆,后续运行继续受影响。
解析、查询、发信和记忆写入各自都可能是合法动作,攻击性来自它们之间的来源、顺序和数据流关系。Microsoft 对 CVE-2025-32711 的记录将问题描述为 M365 Copilot 中可导致网络信息披露的 AI command injection,并标明攻击者无需权限和用户交互。这个真实案例说明,AI 事件的影响可能跨过外部内容、模型解释和网络输出,单独记录一次模型调用无法支撑调查。
Run 因果图连接观察、决定与副作用
Run 因果图是系统声明的操作因果关系。节点表示已经观察到的事件,边表示“该组件使用了这些前序事件产生当前事件”。它不推测模型私有推理,也不声称仅凭时间顺序证明了自然世界中的因果;每条边都由实际消费输入、执行策略或调用工具的组件写出。
[ExternalInput: PDF]
|
v
[ContextAdded: chunk-7] ------> [ModelInvocation: m1]
|
v
[ActionProposed: read-order]
|
v
[PolicyAllowed: p1]
|
v
[ToolResult: sensitive-order]
|
+-----------------+------------------+
v v
[ModelInvocation: m2] [MemoryWrite: candidate]
|
v
[ActionProposed: send]
|
v
[SideEffectObserved: external-mail]
模型并行调用工具、一次结果被多个步骤使用、失败后重试,都会让图形成有向无环图,而非简单调用栈。长期记忆还会产生跨 Run 边:run_a 写入的记忆节点,被 run_b 加入上下文。调查若只按一次会话过滤,就会漏掉持久化影响。
图中需要区分三个层次:ActionProposed 记录模型想做什么,PolicyDecision 记录控制面为何允许或拒绝,SideEffectObserved 由业务权威系统确认现实状态。工具返回“邮件已发送”只是观察;邮件服务中的消息 ID 和收件状态才能证明副作用是否发生。
Run Event 提供跨组件的最小证据
每个组件用统一的 Run Event 记录结构化事实。下面是本系列建议的本地事件契约,并非 OpenTelemetry 已经完整定义的标准字段:
{
"event_id": "evt_...",
"run_id": "run_...",
"action_id": "act_...",
"caused_by": ["evt_..."],
"event_type": "policy.decision",
"occurred_at": "...",
"actor": {
"principal": "agent_...",
"on_behalf_of": "user_...",
"tenant": "tenant_..."
},
"object": {
"type": "order",
"id": "order_...",
"origin": "external|internal|derived",
"classification": "..."
},
"control": {
"policy_version": "...",
"decision": "allow|deny|review",
"reason_code": "..."
},
"effect": {
"effect_id": "effect_...",
"system": "mail|erp|memory",
"operation": "...",
"target": "...",
"status": "requested|confirmed|unknown|compensated",
"reversible": false
},
"versions": {
"release_manifest": "sha256:...",
"model": "...",
"prompt": "...",
"knowledge": "...",
"tool": "..."
},
"evidence_ref": "vault://..."
}
常规事件保存对象 ID、标签、参数摘要、策略版本和结果状态。没有动作或副作用的事件可以省略 action_id 或 effect;发生重试、异步执行和补偿时,稳定的 action_id 与 effect_id 用来把一次授权、一次现实状态变化及其后续处置对上。Prompt 正文、附件与工具返回可能包含个人信息和机密,只在有明确用途的证据库中加密留存,并通过 evidence_ref 受控访问。哈希可以证明调查时看到的是同一份字节,无法解释内容含义;来源标签和业务对象仍要单独记录。
OpenTelemetry Trace提供 Span、父子关系和 Links 等跨服务关联能力,OpenTelemetry Generative AI Semantic Conventions继续规范模型与 Agent 的通用遥测语义。它们可以承载 Run Event,业务授权、信息分类、策略决定和副作用状态仍需应用补充。
应用 / Agent / PDP / PEP ──> Event SDK ──> OTel Collector
业务系统副作用适配器 ────────────────────────┤
版本与制品注册表 ────────────────────────────┤
v
Event Normalizer
|
v
Causal Graph Store
/ \
v v
Streaming Rules Evidence Vault
| |
v v
Control Plane Incident Console
撤权 / 熔断 / 隔离 Replay Lab
业务系统副作用适配器非常关键。只采集 Agent Runtime 会把“提出调用”和“现实改变”混在一起,也看不到异步队列在 Agent 停止后继续执行。ERP、邮件、代码仓库、身份系统和记忆服务应回传权威状态,并关联原 action_id 与 run_id。
检测规则追踪危险路径
确定性规则先保护已知不变量,例如跨租户读取、未审批写操作、凭证进入外部 Sink、已撤销 Capability 继续执行。序列规则再识别单步合法、组合危险的路径;统计异常用于发现尚未建模的变化,例如某场景突然增加新工具、外部目的地或失败后的范围扩张。
对前述客服场景,可以表达一条伪图查询:
MATCH
(i:ExternalInput)-[:CAUSES*]->(r:SensitiveRead)
-[:CAUSES*]->(e:ExternalWrite)
WHERE
r.tenant != i.actor_tenant
OR e.destination NOT IN run.approved_destinations
ACTION
deny(e), isolate(run), revoke(run.capabilities)
这条规则依赖来源、租户、分类、目的地和因果边,语言如何编码隐藏指令不会改变判断。提示注入分类器仍可为外部内容打风险信号,适合提高审核优先级;分类器漏报时,跨域 PEP 继续执行确定性边界,分类器误报时,系统也能根据真实数据流避免把所有附件一律阻断。
图检测的反例来自标签错误。解析器若把外部 PDF 标为内部制度,后续规则会在错误事实之上正常运行。因此要监测标签来源与传播:谁创建标签、哪次转换继承或降级、是否出现缺少 caused_by 的敏感读取。无法解释来源的高敏事件可以进入人工复核或限制输出,具体策略取决于业务后果。
统计异常需要先定义基线分母。客服 Agent 的邮件调用量应按已完成工单数计算,不能只看原始次数;跨域拒绝应按全部跨域尝试计算,模型升级前后再比较相同任务和权限。明确越权不等待统计显著性,异常模型也不宜单独批准高后果动作。
响应沿因果图切断仍可达的后果
事件响应先锁定图中的已知影响:哪些数据已经被读取,哪些外部 Sink 已收到内容,哪些凭证、异步任务和记忆仍有效。控制面可以按 Run、用户、租户、工具版本、目标地址或策略版本撤权,随后要求每个 PEP 返回执行结果。控制台显示“停用”却没有资源侧确认,处置状态仍是未知。
隔离粒度跟随因果图。单个附件只影响一个 Run 时,冻结该 Run 的外发和记忆写入;某 MCP Server 的结果污染多个 Run 时,停用该 Server 并查询所有后继节点;授权策略整体错误时,相关写能力统一降为只读。精确隔离保留未受影响功能,也要求事件和能力标识足够完整。
副作用按可逆性处理。未发送的邮件可以取消,已投递邮件需要确认收件人、通知与泄露范围;订单可能撤销,已经执行的付款还涉及财务追回。补偿动作产生新的 Run Event 并指向原副作用,不能覆盖原记录或把“已补偿”写成“从未发生”。
NIST SP 800-61 Rev.3把事件响应纳入持续的网络安全风险管理,并覆盖准备、检测、响应、恢复和经验反馈。AI 事件沿用这套组织机制,增加上下文来源、模型与知识版本、Capability、工具链、记忆和现实副作用等证据。
隔离重放验证控制点
相同 Prompt 再运行一次,结果可能因采样、模型服务升级、检索排序、时间、外部 API 和业务状态变化而不同。重放环境要冻结能够冻结的模型、Prompt、知识库、工具 Schema、策略和测试数据,记录无法冻结的供应商版本;工具通过 Stub 返回保存过的观察,所有写操作落到模拟系统。
一次有效重放分四步:先根据事件图重建原始前置状态,再确认危险路径能够在隔离环境出现;随后每次只改变一个候选控制,观察预期 PEP 是否阻断;最后围绕同一机制生成文件格式、语言、调用顺序和重试变体,进入回归集。原事件无法稳定复现时,应记录差异和不确定性,不能用一次安全输出宣布根因已经消失。
因果图帮助定位应改变的控制,却不会自动证明单一根因。模型升级、标签丢失和授权缺口可能共同造成结果。通过一次只替换一个变量的对照重放,可以判断修复收益来自模型内拒绝、检索过滤、资源授权还是 Sink 限制,并保留其他层仍可能失效的边界。
恢复从已验证的最小能力开始。先启用只读与内部输出,再逐步恢复外发和写工具;每一步要求旧攻击路径被阻断、业务系统状态完成对账、撤销与熔断仍可用。长期记忆或数据索引受到污染时,恢复范围要覆盖后继 Run,单独回退模型版本无法清除这些状态。
指标同时约束盲区与处置成本
运行报告需要给出能够复核的分母:
- 因果覆盖率 = 能追溯到输入、策略与主体的已确认副作用数 / 已确认副作用总数。
- 策略可观测率 = 带策略版本、决定和理由码的 Action Proposal 数 / Action Proposal 总数。
- 副作用核验率 = 已由业务权威系统确认最终状态的动作数 / 返回成功或未知的副作用动作总数。
- 路径检出率 = 被规则发现的已标注危险路径数 / 回放集中的已标注危险路径总数。
- 正常误阻率 = 被安全规则阻断的正常运行数 / 经人工确认的正常运行总数。
- 撤权完成率 = 已由 PEP 确认失效的能力与异步任务数 / 事件图识别出的待撤销总数。
- 遏制时延 = 从首个可观测危险事件到全部目标 PEP 确认阻断的时间,并报告需要遏制的事件总数和分位分布。
生产环境通常没有完整的攻击真值,因此线上告警命中率不能直接充当检出率。路径检出率来自经过标注的回放、演练与已确认事件;线上数据用于发现分布变化,并通过抽样复核估计误报。抽样估计要报告抽样框、复核数、原始计数与比例区间;跨租户访问、已拒动作仍产生副作用等确定性违规发现一次就进入响应,不等待统计阈值。报告“发现若干异常”而不说明全部运行、被标注样本和规则适用范围,无法比较版本变化。
遥测完整性与数据最小化存在直接取舍。高影响场景应完整保留身份、标签、策略决定和副作用事件,低风险模型 Token 与正文可以采样或不记录;敏感正文进入分离的证据库并采用更短期限。对所有字段统一采样会在最需要调查的危险链上制造断点,永久保存全部 Prompt 又会形成新的敏感数据仓库。
图存储也有成本边界。可以长期保留低体积的对象关系、版本摘要和决定结果,把大附件与完整正文按风险单独留存。第三方模型或工具无法返回稳定版本和细粒度事件时,图中应显式标记观测缺口,并缩小其可用数据、能力与 Sink;用一个供应商请求 ID 填满字段,无法获得同等的调查证据。
运行安全的发布条件可以归结为一条可操作判断:每个高后果副作用都能沿因果边追到主体、输入、授权与版本,控制面能够沿同一张图阻断仍可达的后继动作,业务系统能够证明最终状态。缺少其中任何一段时,系统要降低权限、限制输出去向或保留人工流程,直到盲区与后果相匹配。