LangChain模板注入漏洞分析
漏洞概述
LangChain的提示模板系统存在模板注入漏洞,允许攻击者通过模板语法访问Python对象内部属性。该漏洞影响接受不受信任模板字符串(不仅仅是模板变量)的ChatPromptTemplate和相关提示模板类。
受影响组件
- langchain-core包
- 模板格式:
- F-string模板(template_format=“f-string”)- 已修复漏洞
- Mustache模板(template_format=“mustache”)- 防御性加固
- Jinja2模板(template_format=“jinja2”)- 防御性加固
漏洞影响
能够控制模板字符串(不仅仅是模板变量)的攻击者可以:
- 通过属性遍历访问Python对象属性和内部属性
- 从对象内部提取敏感信息(例如
__class__、__globals__) - 根据传递给模板的对象,可能升级为更严重的攻击
攻击向量
1. F-string模板注入
修复前:
|
|
2. Mustache模板注入
修复前:
|
|
3. Jinja2模板注入
修复前:
|
|
根本原因
F-string模板
实现使用Python的string.Formatter().parse()从模板字符串中提取变量名。此方法返回完整的字段表达式,包括属性访问语法:
|
|
提取的名称未经验证以确保它们是简单标识符。
Mustache模板
设计上使用getattr()作为回退,以支持访问对象上的属性。
Jinja2模板
Jinja2的默认SandboxedEnvironment阻止双下划线属性(例如__class__),但允许访问对象上的其他属性和方法。
受影响用户
高风险场景
如果您的应用程序满足以下条件,则受到影响:
- 接受来自不受信任源的模板字符串(用户输入、外部API、数据库)
- 基于用户提供的模式动态构建提示模板
- 允许用户自定义或创建提示模板
易受攻击的代码示例:
|
|
低风险/无风险场景
如果满足以下条件,则不受影响:
- 模板字符串在应用程序代码中硬编码
- 模板字符串仅来自受信任的受控源
- 用户只能提供模板变量的值,而不能提供模板结构本身
安全代码示例:
|
|
修复方案
F-string模板
F-string模板存在明显的漏洞,其中属性访问语法可被利用。我们添加了严格的验证来防止这种情况:
- 添加验证以强制变量名称必须是有效的Python标识符
- 拒绝类似
{obj.attr}、{obj[0]}或{obj.__class__}的语法 - 只允许简单的变量名:
{variable_name}
修复后 - 这些在模板创建时被拒绝:
|
|
Mustache模板(防御性加固)
作为防御性加固,我们限制了Mustache模板支持的内容以减少攻击面:
- 用严格的类型检查替换了
getattr()回退 - 只允许遍历到dict、list和tuple类型
- 阻止对任意Python对象的属性访问
加固后 - 属性访问返回空字符串:
|
|
Jinja2模板(防御性加固)
作为防御性加固,我们显著限制了Jinja2模板的能力:
- 引入了阻止所有属性/方法访问的
_RestrictedSandboxedEnvironment - 只允许从上下文字典中进行简单的变量查找
- 在任何属性访问尝试时引发
SecurityError
加固后 - 所有属性访问都被阻止:
|
|
重要建议
由于Jinja2的表达能力和完全沙箱化的难度,我们建议仅将Jinja2模板保留给受信任的源。如果需要接受来自不受信任用户的模板字符串,请改用具有新限制的f-string或mustache模板。
修复措施
立即行动
- 审计代码中模板字符串来自不受信任源的任何位置
- 更新到langchain-core的修补版本
- 审查模板使用情况,确保模板结构和用户数据分离
最佳实践
- 考虑是否需要模板 - 许多应用程序可以直接使用消息对象(HumanMessage、AIMessage等)而无需模板
- 将Jinja2保留给受信任的源 - 仅在完全控制模板内容时使用Jinja2模板
技术规格
- 严重程度:高
- CVSS评分:8.3
- 受影响版本:>= 1.0.0, <= 1.0.6 和 <= 0.3.79
- 修补版本:1.0.7 和 0.3.80
参考
- GHSA-6qv9-48xg-fc7f
- langchain-ai/langchain@c4b6ba2
- langchain-ai/langchain@fa7789d
- https://nvd.nist.gov/vuln/detail/CVE-2025-65106