#AI#AI Agent#DevOps

Agent 不可信数据的污点传播:从检索内容到工具参数的强制隔离

外部网页、RAG 片段和工具结果被摘要后仍然不可信。本文设计随数据跨步骤传播的 taint 标签、确定性 sink 策略、审计事件、攻击测试与隔离回滚。

本文要点

  • 主题聚焦:AI、AI Agent、DevOps
  • 适合人群:独立开发者、全栈工程师、AI 应用开发者
  • 核心价值:快速理解背景、实践路径、常见误区和工程建议
作者 @admin·发布于 2026年7月1日·更新于 2026年7月20日

间接 Prompt Injection 的难点不只在模型读到恶意网页,而在内容会经过检索、摘要、记忆和计划多次变形。许多系统只在抓取入口标记 <untrusted>,摘要后却创建没有来源的新字符串,下一轮 Agent 便可能用它选择工具、拼 URL 或申请权限。

Prompt Injection 防御 已说明模型指令不能充当安全边界。本篇进一步把“不可信”做成运行时可传播的元数据,并像静态分析的数据流一样,在高风险 sink 处由确定性策略阻断,而不是再次询问模型“这安全吗”。

值和信任标签必须一起移动

每个进入 Agent 的值都封装为带 provenance 的对象。字段包括来源、租户、敏感级别、污点、证据 ID、生成步骤和策略版本;来源使用有限枚举,不能接受工具自报 trusted=true。

ts
type Tainted<T> = {
  value: T;
  provenance: Array<{ source: string; evidenceId: string }>;
  taints: Array<"untrusted_instruction" | "external" | "sensitive" | "cross_tenant">;
  tenantId: string;
  policyVersion: string;
};

function derive<T>(value: T, inputs: Tainted<unknown>[]): Tainted<T> {
  return {
    value,
    provenance: inputs.flatMap((item) => item.provenance),
    taints: [...new Set(inputs.flatMap((item) => item.taints))],
    tenantId: requireSameTenant(inputs),
    policyVersion: ACTIVE_POLICY,
  };
}

传播规则应单调:合并时取 taint 并集,翻译、摘要、embedding、rerank 和模型重写都不能移除标签。只有确定性变换能降级某类 taint;JSON Schema 只证明形状,人工核验只批准具体动作,都不能把自然语言永久标成可信。

RAG 场景还要保留文档 ACL 和租户标签。RAG 检索权限控制 在召回前过滤证据,污点传播则保证召回后的摘要和引用不会丢失该边界。任何混入不同租户的数据在 requireSameTenant 处失败,不能靠模型“只使用属于当前用户的部分”。

对高风险 sink 写明确矩阵

source 只描述来源,sink 决定能否使用。可以允许 external_web 进入摘要和引用候选,但禁止它决定工具名、扩大 capability scope、修改 system policy、构造任意网络目标或进入 shell。带 sensitive 的值可以进入本租户受控数据库写入,却不能进入外部 HTTP body。工具参数中的业务文本可带 taint 传递给执行器,由执行器按字段策略处理。

text
sink=planner_context      external=allow_as_data  sensitive=redact
sink=tool_selector        untrusted_instruction=deny
sink=capability_request   external=deny           cross_tenant=deny
sink=network_destination  external=deny_unless_allowlisted
sink=external_body        sensitive=deny
sink=audit_log            sensitive=hash_or_drop

策略输入必须来自结构化标签和可信会话,不接受模型输出 risk=low。当策略拒绝时返回稳定 code、触发的 taint、来源证据和允许的替代动作,例如只生成草稿或请求人工批准。这样 Agent 可以恢复任务,但无法通过改写同一内容洗掉污点。

覆盖记忆、子 Agent 与工具回流

长期记忆同时存储 taint、租户、证据 ID 和过期时间,检索后原样恢复。否则摘要入库后会失去污染来源,也无法在源文档清理时隔离所有派生记忆。

委派给子 Agent 时,任务 envelope 携带输入标签和允许 sink,子 Agent 只能增加限制,不能把 external 改为 trusted。MCP 多租户隔离 中的可信租户上下文同样适用。工具输出默认带 tool_output 与工具自身信任级别;即使是内部工具,也可能返回数据库里由攻击者写入的文本,不能因为传输通道受信就信任内容。

Trace 只记录 taint 数量、策略决策、证据 ID 哈希和拒绝原因。AI Agent 可观测性 可承载这些步骤级安全事件。

用跨步骤攻击测试证明传播没有断点

测试不能只发一句“忽略之前规则”。准备恶意 PDF、网页评论、工单字段和工具返回,让指令先被摘要、写入记忆、传给子 Agent,再诱导调用外发工具。断言每一跳 taint 仍存在,危险 sink 被运行时拒绝,模型即使声称已验证也无法执行。再加入合法外部数据,确认它仍能用于摘要和引用,避免策略退化为所有内容都不可用。

属性测试随机组合 source、transform 和 sink,验证派生 taint 不少于输入并集,且没有 sanitizer 证明时信任不能上升。策略升级还要回放历史拒绝样本。

事故隔离和回滚必须 fail closed

发现 taint 在某个 transform 后丢失时,先禁用相关写工具和外部出口,保留只读摘要能力;按 evidence ID 隔离派生记忆、暂停受影响 run,并撤销它们取得的短期权限。不要简单删除审计记录,也不要用新 Prompt 继续跑旧上下文。

修复后恢复上一份已签名的传播策略与 envelope schema,在隔离环境回放攻击链,确认每个 sink 都产生预期 decision。先开放只读,再开放可逆写入,最后恢复外部副作用。回滚的安全基线应是“未知标签拒绝高风险 sink”,而不是为了兼容旧任务把未知值视为可信。

污点传播不能保证模型不受恶意文本影响,但它能保证影响不会悄悄变成权限和数据流。只要来源随值移动、降级需要证据、sink 由确定性策略控制,Agent 即使做出错误判断,也会被限制在可观察、可撤销的边界内。

延伸阅读

Related

相关推荐