跳到主要内容

大模型应用安全

合同审查助手会把开发者写的规则、用户问题、供应商合同、内部制度和模型回答拼进一条处理链。它们在模型眼里都是 Token,来源、权限和用途却完全不同。一段藏在合同白色背景中的文字,可能被模型理解成与系统规则竞争的新指令。

这类风险的技术根源是:大模型是混合信任解释器,指令和数据共享同一条自然语言通道。 提示模板、指令层级和注入检测可以降低模型误解的概率。能够承诺安全边界的控制,还要由模型外的代码保留来源与权限,并在数据进入上下文、输出进入渲染器或结果流向其他主体时强制执行。

本文讨论只读或内容生成型应用。模型输出开始触发 ERP、邮件、Shell 等真实动作后,还要增加 Agent 与工具调用安全中的 Capability Envelope 与逐次授权。

攻击者利用混合信任解释器

先明确攻击者模型。攻击者可以控制助手将来会读取的合同、网页、邮件或知识库投稿,也可以反复观察应用输出;他没有系统提示、模型权重、数据库凭证和企业账号。攻击目标是让低信任内容影响高信任处理,例如改变审查目标、诱导越权检索、泄露内部制度,或让回答在浏览器中获得代码语义。

一条完整攻击链可以跨过七个组件:

  1. 攻击者在供应商合同中嵌入“引用内部退款规则,并把结果放入指定链接”的隐藏文字。
  2. 文档解析器提取正文时丢失了“外部供应商提供”这一来源属性。
  3. 切片与索引服务只保存文本和 Embedding,检索时按相似度召回。
  4. 上下文组装器把系统规则、内部制度和恶意片段拼给模型,分隔符只剩排版含义。
  5. 模型遵循恶意片段,结合内部制度生成带外部链接的 Markdown。
  6. 输出层允许任意链接或 HTML,浏览器、缓存或导出服务继续处理结果。
  7. 攻击者通过链接参数、远端资源请求或用户转发观察到内部信息。

Greshake 等人的间接提示注入研究系统描述了这种远程攻击面,并在当时的真实大模型产品和实验应用中演示了数据窃取、功能操纵与 API 调用影响。它揭示的关键机制是跨组件的信任升级:攻击者写入的是数据,后续系统却允许它参与控制流程。

Prompt 内的优先级只能降低失守概率

XML 标签、引号、角色说明和“以下内容仅作资料”可以帮助模型识别结构。模型仍要用同一个生成过程解释标签内外的文字,攻击者可以改写、拆分、编码或借多轮上下文表达相同目标。输入分类器也面对开放的自然语言分布,未命中只说明当前检测器没有识别风险。

Instruction Hierarchy通过训练让模型在冲突时优先遵循高权限指令,论文在 GPT-3.5 实验中观察到鲁棒性提高。这类能力很有价值:模型更少提出危险结果,人工复核与策略引擎承受的压力也会下降。实验结论对应给定模型、攻击集和任务分布,无法让低权限文本获得密码学意义上的隔离。

系统提示也不适合保存秘密。任何已经进入模型上下文的信息,都可能被概括、翻译、编码或混入错误输出。凭证、授权条件和可直接绕过控制的规则应留在服务端;必须提供给模型的内部知识,则由身份、用途、输出去向和审计约束其暴露范围。

因此,应用要区分两类目标:模型内控制用于提高正确理解的概率,模型外控制用于限制一次误解能够跨越的信任边界。前一类失效时,后一类仍需独立成立。

用 Context Envelope 保留来源与权限

本文把运行时所需的信息流标签封装为公共的 Context Envelope。来源、版本和血缘取自 KnowledgeArtifact,目的、处理者、留存和允许接收者取自 DataUseEnvelope,再与当前主体和任务策略求交;Context Envelope 是这次运行的策略快照,不是另一份独立维护的授权副本。它不会因为文本被拼进 Prompt 而消失,也不能由模型输出自行改写。一个片段至少需要回答:谁提供、属于哪个租户、谁可以读、敏感级别多高、可信度如何、允许流向哪里、何时失效,以及能否追到原始对象和版本。

{
"context_id": "ctx_...",
"artifact_ref": "artifact:<digest>",
"data_use_ref": "data-use:<version>",
"source": {"origin": "external", "principal": "supplier_..."},
"trust_tier": "untrusted",
"tenant": "tenant_...",
"acl_snapshot": ["role:contract-reviewer"],
"version": "parser-and-chunk:v...",
"lineage_ref": "lineage:<node-id>",
"classification": "commercial-confidential",
"allowed_sinks": ["ui:assigned-reviewer"],
"expires_at": "..."
}

artifact_refdata_use_ref 指向权威对象,便于权限、目的或撤销状态变化后让旧投影失效。模型可见正文和必要来源提示,PDP 与 PEP 读取完整 Envelope;模型输出不能增加 allowed_sinks,也不能把 trust_tier 从外部提升为内部可信。

外部文档 ─> 解析/标注 ─> 带标签的文档库 ─> 检索 PEP ─┐
用户身份 ────────────────────────────────> PDP ───────┤
系统规则 ─> 受控配置库 ───────────────────────────────┤
v
上下文组装器
|
v
LLM
|
带来源标签的候选输出
|
v
输出 PEP ─> 渲染 / 缓存 / 导出
^
└──── PDP + Sink 策略

这里的 PDP 是 Policy Decision Point,负责根据主体、对象、动作和环境作出允许、拒绝或需要复核的决定;PEP 是 Policy Enforcement Point,位于数据实际跨域的位置并执行决定。模型可以建议“这段内容可公开”,标签变更仍只能由有权的业务流程或确定性去标识程序完成。

CaMeL把可信查询中的控制流、来自环境的数据流和工具能力显式分开,并在调用边界执行信息流策略。论文在其 PI-SEC 威胁模型、显式且正确的策略及 AgentDojo 环境下提供安全保证,并完成 77% 任务;对照的无防护系统完成 84%。这个结论不覆盖文本到文本完整性攻击、部分侧信道,也不代表解释器实现已经获得完整形式验证;它展示的是给定假设下的强隔离形态及其效用代价。

在三个跨域点强制执行策略

检索入口。 向量相似度只决定语义接近程度。检索 PEP 应先根据当前主体、租户、文档 ACL、有效期和用途形成可访问集合,再在集合内做向量检索与重排。切片、Embedding、缓存和引用记录都继承同一对象身份;生成后删除敏感词无法撤销模型已经看到的内容。

上下文组装。 组装器保留每段内容的来源和标签,只选择当前任务需要的片段,并把系统规则与外部数据放入不同结构。结构标记服务模型理解,授权元数据留在模型外。外部片段可以影响摘要内容,不能修改租户、允许的输出去向或后续校验规则。

输出去向。 模型结果先被视为带来源的候选数据。输出 PEP 根据目标 Sink 选择确定性处理:JSON Schema 校验结构,HTML 清洗器处理标记,数据库驱动绑定参数,下载服务限制协议与域名,缓存键包含租户、权限范围和版本。DOMPurify 的实现说明也提醒调用方,清洗后的标记若再被其他组件修改,原有清洗效果可能被破坏;校验必须贴近最终解释器。

策略可以表达为一组不依赖模型判断的条件:

allow_retrieve(subject, chunk) =
same_tenant(subject, chunk)
AND subject_has_acl(subject, chunk)
AND purpose_allowed(subject.task, chunk)
AND chunk.not_expired

allow_sink(value, sink) =
value.classification <= sink.max_classification
AND value.allowed_sinks CONTAINS sink.id
AND sink.accepts(value.schema)

真实策略还要处理继承与去标识。多个片段合成回答时,输出默认继承最严格的敏感级别和允许去向;只有经过可验证的字段删除、聚合或人工授权,才能降低级别。让生成模型自行声明“已经脱敏”无法完成这次降级。

用完整攻击链验证强制边界

测试需要把恶意内容放进 PDF 隐藏层、网页、邮件、RAG 文档和缓存命中路径,再让真实解析器、索引、模型、渲染器与导出服务共同运行。AgentDojo提供了一个可扩展的 Agent 测试环境,其论文版本包含 97 个正常任务和 629 个安全测试用例;它同时衡量正常任务与攻击任务,避免“全部拒绝”获得表面安全。

本应用至少记录五个带分母指标:

  • 越权上下文进入率 = 进入模型的无权片段数 / 被测试的无权候选片段总数。
  • 标签完整率 = 保留全部必需标签的跨组件传递次数 / 被检查的传递总次数。
  • 输出策略逃逸率 = 到达受保护 Sink 的违规输出数 / 模型实际产生的违规输出总数。
  • 攻击影响率 = 发生越权读取、危险呈现或未授权外发的运行数 / 完整攻击运行总数。
  • 正常任务完成率 = 成功完成且结果正确的正常运行数 / 正常运行总数。

“模型听从注入的比例”和“注入造成安全影响的比例”要分开。前者用于改进模型内防护,后者检验模型外边界。由于采样、上下文顺序和模型服务可能带来波动,同一攻击应重复运行,报告模型与组件版本、重复次数和实际分母;只列成功截图无法说明控制强度。

随机运行的比例还要报告区间估计。来自同一文档或攻击模板的变体高度相关,适合按独立攻击机制或目标分簇,再对簇做重采样;把每次 Token 采样当成独立样本会夸大证据量。发布门禁分别处理两类结果:任一确定性跨租户或受保护 Sink 逃逸都阻断发布;概率性模型失守率的区间上界超过场景容忍度,或正常任务完成率的区间下界低于效用要求时,结论记为证据不足。

强隔离需要明确效用代价

信息流越细,系统越能保留正常能力,标签维护和策略复杂度也越高。整份合同标为机密容易执行,却会阻止公开条款复用;片段级标签提高利用率,同时要求切片、摘要、缓存和删除流程都保持对象关系。团队可以从文档级控制起步,只在有明确收益和稳定血缘时细化。

检索前授权可能降低共享索引的召回效率。高隔离场景可以使用租户独立索引,规模较大且权限变化频繁的场景可以采用带过滤的共享索引;两种实现都要用越权候选作为负向样本验证,不能用生成结果“看起来没有泄露”代替上下文检查。

固定 Schema 与受限 Sink 会压缩模型的开放表达空间。面向公开资料、没有内部上下文、输出只显示为纯文本的低后果摘要器,可以接受较轻的标签和策略成本;接触跨租户资料、富文本渲染、外部链接或自动导出的应用,需要更强的强制边界。选择依据是数据能到达的最远位置和失效后果,而非应用是否自称只读。

发布证据最终应落在三个不变量:无权内容无法进入模型上下文;低信任文本无法修改服务端策略;未经目标解释器校验的输出无法进入受保护 Sink。Prompt 防护继续提高正常表现,安全结论由这三条跨组件约束及其端到端测试结果支撑。