Skip to content

Trust Boundaries

ToLO 威胁模型核心是:不可信数据通过五种通道之一进入 LLM 输出,再被框架代码错误地当作可信数据处理。本节先列攻击者能力 + 通道 + 被保护对象 + 五条边界,再给出判断 ToLO 的三问法和它的实际应用例子。

威胁模型的作用是约束讨论范围。ToLO 不假设攻击者已经拿到服务器 shell,也不研究模型训练阶段的全部攻击;它只关心一个远程低权限攻击者能否影响 LLM 输出,并让该输出触达敏感程序操作。

这一页的结构

  1. 先修概念:边界 = 信任级别变化的位置
  2. 攻击者能力(有什么 / 没什么)
  3. 五个攻击者通道(简要;详细在 attacker-channels)
  4. 六类被保护对象
  5. 数据流上的五条边界
  6. 判断 ToLO 的三问法
  7. 不在本章范围的内容
  8. 自测

先修概念:边界是什么

边界是”信任级别发生变化”的位置。

举例:

  • 用户输入进入服务器时是边界(不可信 → 应用处理域)。
  • 应用要把数据写入数据库时是边界(应用内部 → 持久化层)。
  • 应用要执行 shell 命令时是边界(应用内部 → OS 解释器)。

每条边界的关键问题是:穿过边界前,数据是否被相应的检查 / 转换 / 隔离?

ToLO 的关键边界

ToLO 主要关心两条:

  • 模型边界:模型输出从 token 变成程序数据。这一刻,数据第一次成为程序可见值
  • 执行边界:程序数据被拿去执行真实操作(shell / SQL / open / requests / eval / pickle / Template)。

如果模型边界没把输出标成不可信,执行边界又没检查权限,就形成 ToLO。

§1 攻击者能力

攻击者的能力

ToLO 假设攻击者是远程低权限用户:

  • ✅ 可以与目标 LLM 应用正常交互(发送 prompt、提交表单、上传文件 等)。
  • ✅ 可以提供任意文本输入(包括其他用户能看到的评论、issue、commit 描述等)。
  • ✅ 可以发布公开内容(网页、博客、issue、PR、文档),让被 agent 抓取或被 RAG 索引。
  • ✅ 可以控制某个第三方工具的响应(自己运营的 MCP server、被劫持的 API、伪造的搜索结果)。
  • ✅ 可以发布或替换被应用加载的模型权重(恶意 HuggingFace 上传、劫持反向代理 endpoint)。

攻击者没有的能力

  • ❌ 目标系统的代码读取(不能 cat src/)。
  • ❌ 目标系统的 shell access(不能 SSH 进去)。
  • 文件系统直接访问(不能 ls /etc/)。
  • 数据库直连(不能 psql -h db)。
  • ❌ 受害用户的 credential(不能用 X 用户的 cookie / session)。

这意味着 ToLO 不是”本地恶意用户调用危险 API”问题。攻击者的入口仍是应用暴露的正常交互面,只是 LLM 编排层把这些交互转化成了更强的程序能力

一个重要限制:不需要源码

ToLO 的很多路径来自公开功能本身:聊天、上传文档、连接工具、触发 agent workflow。攻击者不需要读源码就能尝试这些路径 —— 公开 API 文档、用户手册、demo 视频通常足够。

这也是 ToLO 检测的紧迫性来源:当攻击者不需要源码,公开 SaaS / 开源 agent 都是受攻击面

§2 五个攻击者通道(简要)

本论文不预设单一通道,把”LLM 输出对攻击者可影响”作为抽象前提,承认可经以下任一通道实现:

通道简述能力前提
C1 直接 prompt injection攻击者直接发送 prompt用户即攻击者(零前置)
C2 间接 prompt injection攻击者发布网页/文档,被 agent 抓取或 RAG 检索进 prompt能发布公开内容
C3 RAG 索引投毒攻击者控制被索引语料库中的若干条目能写向量库 / wiki / 知识库
C4 工具响应控制攻击者控制 LLM 调用的工具(搜索 API、MCP server、第三方 plugin)返回内容能运营或劫持第三方服务
C5 模型供应链污染攻击者发布或替换被应用加载的模型权重 / endpoint能在模型仓库上传或控制反代

ToLO 的结论独立于具体通道。即使 prompt injection 被完美防御,C3 / C4 / C5 仍可触发 ToLO。

因此案例复盘中不需要证明某个特定 prompt injection 技巧永远有效。只要能说明 LLM 输出存在攻击者可影响通道,并且该输出进入危险 sink,就可以进入 ToLO 判定

详细展开(每个通道的可达 source 子集、触发条件、防御对应)见 Attacker Channels

§3 六类被保护对象

ToLO 关心攻击者影响程序能做的事,因此被保护对象按”能做哪些坏事”分:

被保护对象不应被攻击者影响的事典型 ToLO 子类
进程完整性执行攻击者指定代码ToLO-Exec, ToLO-Deser
文件系统读写攻击者指定路径,特别是 /etc/~/.ssh/、应用密钥目录ToLO-Path
网络出口请求攻击者指定 URL,特别是内网与 cloud metadata endpointToLO-SSRF
数据库执行攻击者指定 SQL,特别是 DROP / UPDATE / 条件操纵ToLO-SQL
密钥与凭据环境变量、配置、API key、token 外泄任意子类的下游放大
其他用户的数据多用户应用中 A 的数据被 B 的 LLM 交互泄露或修改任意子类

初学者可以把这六类理解成”不能让模型输出随便碰的东西”。只要 LLM 输出能影响这些对象,就必须有明确边界

注意”密钥与凭据”和”其他用户数据”通常不是 sink 本身,而是下游放大:

LLM 输出 → open(攻击者控制路径) → 读到 /app/.env → exfiltrate
↑ 凭据外泄是后果

写报告时,sink 子类填实际 sink(这里是 ToLO-Path),后果填被保护对象(凭据外泄)。

§4 数据流上的五条边界

把整条 LLM 应用栈按信任级别切五段:

[攻击者控制] ──①──► [应用内可见] ──②──► [模型黑盒]
[结构化对象] ◄──④── [tool 参数] ◄──⑤── [真实执行环境]

五条边界:

编号名字信任变化检查内容
输入边界外部 → 应用内用户输入 / 网页 / 上传 / RAG 进入 prompt 时的验证 / 内容来源标记
模型边界应用 → 模型没什么应用层能检查(模型内部),只能在 prompt 设计上做隔离
解析边界模型 → 应用可读对象OutputParser / function calling / JSON parser 转结构化
工具边界应用对象 → 工具参数agent / workflow 把字段传给 tool 前的检查
执行边界工具参数 → 真实操作tool 内部进入 sink 前的最后检查(sanitizer 应当在这里)

边界越靠后,后果越具体:

  • ① 输入边界失守:模型可能被诱导
  • ② 模型边界:不可控
  • ③ 解析边界失守:出现意外字段类型
  • ④ 工具边界失守:危险参数被传入
  • 执行边界失守:RCE / SQL injection / SSRF / 文件读写 → 真正的 ToLO 后果

ToLO 的研究重点落在 ③/④/⑤:污染输出如何从模型边界一路走到工具边界和执行边界。

§5 边界例子:网页 → 模型 → URL → 请求

来看一段具体数据流:

[evil.example/blog.html] ──①──► [agent.fetch_url] ──②──► [LLM 上下文]
[requests.get(url)] ◄──⑤── [tool args] ◄──④── [LLM 输出 tool_call]

这里至少有四个边界:

  1. 网页内容进入系统:输入边界 ①。
  2. 文档进入 prompt:模型上下文边界(②)。
  3. LLM 输出 URL:模型边界 → 解析边界 ③ → 工具边界 ④。
  4. URL 被请求:执行边界 ⑤。

ToLO 重点检查最后两步:

  • ④ 模型输出 URL 是否被当成可信 URL?
  • requests.get 之前有没有 host allowlist、内网阻断和 capability?

如果都没有,这是教科书级别 ToLO-SSRF

§6 判断 ToLO 的三问法

碰到一段不确定的代码或一个不确定的案例时,用三问法快速判断:

① 这个值是否来自或受 LLM 输出影响?(含 C1-C5 任一通道)

② 这个值是否进入了会改变程序行为的敏感操作?(六类被保护对象之一)

③ 中间是否缺少与 sink 类型匹配的验证、约束、隔离或人工确认?

三问都成立 → 进入 ToLO 分析

边界情况

  • 只有①成立(LLM 输出存在,但没进敏感操作) → 通常只是 LLM 内容安全或 prompt injection 问题,不是 ToLO。
  • 只有①②成立(进了敏感操作,但有看似的 guard) → 看 guard 是否真的类型匹配。错配的 guard 不算 sanitizer。
  • 三问都成立但 guard 是”人工确认” → 还要确认人看到的是将被执行的真实动作(精确路径、精确 SQL、精确 URL),而不是模型给出的自然语言摘要(“我准备读一个 config 文件” — 含糊,不算 guard)。

三问法应用例子

例 A:LangChain LLMMathChain(CVE-2023-29374)

# 简化伪代码
expr = llm.invoke(prompt).content
result = PythonREPL().run(expr)
  • ① LLM 输出影响吗? (C1: 用户问”算 2024 的平方” 可能被改成”算 __import__('os').system(...)”)
  • ② 进入敏感操作? (PythonREPL.run = exec)
  • ③ 缺类型匹配 guard? (无 sandbox、无 capability、无 numexpr 等收窄)

→ ToLO 三问全成立 → ToLO-Exec 案例。

例 B:LLM 输出文本仅展示到聊天框

answer = llm.invoke(question).content
return render_template("chat.html", answer=answer) # autoescape=True
  • ① LLM 输出影响吗?
  • ② 进入敏感操作? 看情况 — HTML autoescape 时,内容只是被展示,不进入 sink。
  • ③ 略。

→ 只满足 ①,不构成 ToLO。属于”LLM 内容质量”问题,不属本研究。

例 C:tool 拿了模型输出但有 capability gate

@tool
def read_doc(doc_id: str) -> str:
"""读取指定文档"""
if doc_id not in CURRENT_SESSION.allowed_docs: # ← capability
raise PermissionError()
real_path = DOC_REGISTRY[doc_id] # ← allowlist 映射
return Path(real_path).read_text()
  • ① LLM 输出影响吗?
  • ② 进入敏感操作? (open)
  • ③ 缺类型匹配 guard? capability + allowlist 双重 sanitizer,且都类型匹配。

→ ToLO 不成立(已正确防御)。

如果 capability 列表本身是 LLM 决定的,那 capability 就不算了。Capability 必须比模型输出更可信

§7 不在本章范围内

ToLO 不讨论:

  • GPU 侧信道、模型权重窃取:属于模型 IP / 隐私研究。
  • 训练数据抽取:属于隐私研究。
  • 闭源 SaaS 内部策略:无源码可分析。
  • 业务逻辑欺诈:如果纯粹是逻辑层错误而非 LLM 输出被误信任,不是 ToLO。
  • “模型回答错了”本身:幻觉、偏见、事实错误属于 model alignment / safety,不属 ToLO 除非错误回答被程序当成可信动作执行。
  • DoS / token 烧钱:成本问题,不属安全 trust model。

只有当错误或可控输出被程序当成可信数据并驱动敏感操作时,才进入本章威胁模型。

§8 自测

判断下面场景是否进入 ToLO 威胁模型:

  1. 用户让聊天机器人胡编了一个事实。
    • 通常不进入,除非这个事实被程序当成动作执行。
  2. 攻击者投毒 RAG 文档,让模型输出一个内网 URL,应用自动请求。
    • 进入。C3 通道 + ToLO-SSRF
  3. 管理员在服务器上手工运行恶意脚本。
    • 不进入。攻击者能力已超过远程低权限设定,且与 LLM 输出无关。
  4. 用户用 emoji 让模型回答里出现彩蛋。
    • 不进入。属于 model behavior,不影响程序敏感操作。
  5. 应用允许员工提交 SQL,模型润色后执行。
    • 进入。即使原始 SQL 来自员工(C1 类似),模型润色环节让攻击面扩大,且最终执行进了 SQL sink。ToLO-SQL
  6. agent 用了 SandboxedEnvironment 的 jinja2,模板字符串固定,模型只填变量。
    • 不进入C_SAFE^parameterized 在 template 上类型匹配 → 已防御。
  7. agent 用了 RestrictedPython 跑模型生成的代码。
    • 可能进入。RestrictedPython 历史多次被绕,需评估具体版本和 globals 配置;不能默认它就是 C_SAFE^capability

下一步阅读