系统:运行中
← 返回所有攻击
SUPPLY CHAIN CRITICAL NEW

聊天模板即代码:LLM 推理服务器中的 Jinja2 模板注入(SSTI)

CERT/CC 的 VU#915947(2026 年 4 月 20 日)记录了 CVE-2026-5760,这是 SGLang 中一个 CVSS 9.8 的远程代码执行漏洞:恶意 GGUF 模型文件携带的 Jinja2 聊天模板会在服务器上执行 Python。它与此前的「Llama Drama」及 vLLM 漏洞属于同一类。

2026-06-19 // 6 min affects: sglang, llama-cpp-python, vllm, gguf, ai-inference-infrastructure

这是什么?

2026 年 4 月 20 日,CERT 协调中心发布了 VU#915947,描述了 CVE-2026-5760 —— SGLang 中一个 CVSS 9.8 的远程代码执行(RCE)漏洞。SGLang 是一个被广泛部署的大语言模型开源推理服务框架(该项目获得超过 2.6 万个 star、5500 多次 fork)。触发条件既不是网络数据包,也不是畸形请求,而是一个模型文件。一个被构造的 GGUF 模型携带聊天模板,一旦模型被加载、且有请求到达 rerank 端点,攻击者提供的 Python 代码就会在推理服务器上执行。

它的意义超出了单一项目,因为 CVE-2026-5760 在性质上并不新鲜。它与 CVE-2024-34359(即「Llama Drama」,2024 年披露、CVSS 9.7、llama-cpp-python 中已修复的 RCE)以及 vLLM 公告 CVE-2025-61620(2025 年底加固了同一攻击面)属于同一类漏洞。三个不同的框架,一个反复出现的错误:把模型提供的聊天模板当作惰性数据,而它其实是可执行代码。

工作原理

现代分词器都附带 chat_template:一个 Jinja2 模板,用于把原始消息格式化成模型所期望的精确 token 序列。该模板随模型工件一起传递 —— 在 GGUF 文件中,它存储在 tokenizer.chat_template 元数据字段里。当服务器加载模型时,会读取这段字符串,并在请求时连同用户数据一起渲染。

缺陷在于使用了功能完整、未受限的 Jinja2 引擎进行渲染。根据 CERT/CC 与报告者(研究员 Stuart Beck)的说明,SGLang 在 entrypoints/openai/serving_rerank.py 中使用了 jinja2.Environment(),而非 Jinja2 的 ImmutableSandboxedEnvironment 来渲染模型提供的模板。未沙箱化的 Jinja2 环境会暴露 Python 对象内部结构,这正是**服务端模板注入(SSTI)**的典型条件 —— 而服务器进程中的 SSTI 即等同于任意代码执行。

整个端到端流程无需提供任何 payload 即可描述:

# 易受攻击的写法:用 Jinja2 的全部能力渲染模型提供的模板
from jinja2 import Environment
template = Environment().from_string(tokenizer.chat_template)  # 不可信输入!
rendered = template.render(messages=...)                       # [REDACTED] 在此执行

攻击者发布一个 GGUF 模型,其 chat_template 包含一段 SSTI 表达式以及一个触发短语(在已披露的案例中是 Qwen3 reranker 的触发短语),将执行引导至有漏洞的 rerank 代码路径。受害者下载并部署该模型 —— 通常来自 Hugging Face 这类公共模型库 —— 第一个到达 /v1/rerank 的请求就会渲染该模板并执行其中嵌入的代码。无需任何凭据。

为什么重要

推理服务器越来越贴近网络,且常以较高权限运行(GPU 访问、云元数据、内网可达)。因此,热门模型库上的单个被投毒模型,就能把「我下载了一个模型」变成「攻击者在我的 GPU 机器上拿到了 shell」。由于恶意指令存在于工件之中,每一个下游部署该模型的用户都会继承这一沦陷 —— 这是供应链失效,而非孤立的 bug。

反复出现这一点才是真正的教训。同一根因之所以先后出现在 llama-cpp-python、vLLM 和 SGLang 中,是因为聊天模板的处理逻辑在整个生态中被复制和重新实现。只要某个框架在不沙箱化的情况下渲染模型携带的模板,这个 bug 就潜伏其中。根据 CERT/CC,针对 CVE-2026-5760,在协调过程中未能取得厂商补丁,因此在披露时运营方必须自行缓解。

防御

  • 对每一个模型提供的模板都进行沙箱化。 使用 Jinja2 的 ImmutableSandboxedEnvironment 渲染聊天模板,绝不使用裸的 Environment()。这是 CERT/CC 的首要建议,也是封堵此前各案例的修复方式。
# 缓解措施:在沙箱环境中渲染不可信模板
from jinja2.sandbox import ImmutableSandboxedEnvironment
template = ImmutableSandboxedEnvironment().from_string(tokenizer.chat_template)
  • 把模型文件当作不可信代码,而非数据。 只加载来自可信来源的模型,固定到具体的修订版本/commit 哈希,并校验校验和或签名。模型库就是一条软件供应链。
  • 在投入服务前检查 tokenizer.chat_template 在模型准入环节,对任何引用属性访问、内置函数或超出简单消息格式化范围的模板进行标记。
  • 控制影响范围。 以低权限、网络隔离的方式运行推理服务器;阻断出站流量;切断云元数据访问。一旦 SSTI 触发,是最小权限决定了它究竟是麻烦还是入侵。
  • 修补并跟踪整个漏洞类,而不仅是单个 CVE。 保持 llama-cpp-python、vLLM、SGLang 及类似推理栈为最新版本,并审计自研的模板渲染代码,查找相同的 Environment() 写法。

状态

项目取值
标识CVE-2026-5760 / CERT VU#915947
CVSS9.8(严重)
受影响SGLang(/v1/rerank,GGUF 聊天模板渲染)
根因使用 jinja2.Environment() 而非 ImmutableSandboxedEnvironment
披露2026 年 4 月 20 日(CERT/CC)
补丁协调期间未获得(通过沙箱化缓解)
同类CVE-2024-34359「Llama Drama」(已修复);vLLM CVE-2025-61620(已修复)

关键日期:2024 年 —— Llama Drama(CVE-2024-34359)。2025 年底 —— vLLM 修复(CVE-2025-61620)。2026 年 4 月 20 日 —— SGLang 披露(CVE-2026-5760)。

本文出于防御目的介绍一类已公开披露的漏洞,并刻意省略任何可用的利用代码。

Sources