圣诞不想要礼物,只想要你秘密:LangGrinch 正面狙击 LangChain Core
LangChain 核心库存在一个严重的反序列化漏洞(CVE-2025-68664),允许攻击者通过构造包含特殊 lc 键的数据来利用其内部机制。这种攻击可能通过单次文本提示触发,导致环境变量泄露、任意对象实例化甚至潜在的代码执行。由于该漏洞位于核心库中且 LangChain 应用广泛,其影响范围巨大。官方已发布修复补丁,并强调所有开发者应将大语言模型的输出视为不可信输入,加强对序列化流程的安全管理。
为什么这个漏洞值得特别关注
- 位于核心库: 这不是某个特定工具或集成功能的 bug,而是存在于 langchain-core 自身的核心 API (
dumps()/dumpd()) 中。 - 影响范围巨大: 从下载量来看,LangChain 是全球部署最广泛的 AI 框架组件之一。截至 2025 年 12 月下旬,其总下载量已达数亿次。
- 单次提示即可触发: 攻击并非简单地让受害者加载一个恶意文件。更微妙的路径是,大语言模型 (LLM) 的输出可以影响
additional_kwargs等字段,而这些字段在框架的正常功能(如流式日志)中会被序列化和反序列化。这意味着,一次文本提示就可能触发一条复杂的内部利用链。
补丁已在 1.2.5 和 0.3.81 版本中发布。如果您在生产环境中使用 LangChain,请尽快升级,因为这个问题比看起来更棘手。
漏洞原理简述
LangChain 使用一个特殊的内部序列化格式,其中包含 lc 标记的字典代表 LangChain 对象。该漏洞的关键在于,序列化函数 dumps() 和 dumpd() 未能正确处理用户控制的、恰好也包含了保留键 lc 的字典。
因此,一旦攻击者能够让 LangChain 的某个循环先序列化、再反序列化包含 lc 键的恶意内容,他们就能实例化一个不安全的任意对象,从而触发多种对攻击者有利的路径。
最严重的后果包括:
- 从环境变量中窃取密钥: 当反序列化操作以
secrets_from_env=True模式执行时,就可能发生这种情况。值得注意的是,直到补丁发布前,这都是默认设置。 - 在预先批准的命名空间内实例化对象: 这可能在类的构造函数中触发副作用,例如网络调用或文件操作。
- 在特定条件下可能导致任意代码执行。
此漏洞被归类为 CWE-502:不受信任数据的反序列化,CVSS 评分为 9.3 (严重)。
漏洞的发现过程
安全研究始于一个反复被提出的基本问题:
AI 应用中的信任边界在哪里?开发者真的清楚这些边界吗?
研究人员发现,尽管已有大量关于 LangChain 工具和集成的研究,但针对核心库的发现却很少。通过从反序列化等潜在的攻击“接收端”逆向分析,研究人员最终定位到了问题。
这个 bug 不是代码写错了,而是缺少了必要的代码。dumps() 函数根本没有对用户控制的、包含 lc 键的字典进行转义处理。这是一个在序列化路径上被忽略的漏洞,而不是在反序列化时。正因如此,这个漏洞在两年半的时间里一直未被发现。
技术细节深入分析
LangChain 的 load() / loads() 函数并不会实例化任意类,而是会根据一个允许列表进行检查。但问题在于,这个允许列表默认包含了 langchain_core、langchain_openai、langchain_aws 等多个生态包中的类。
密钥泄露路径
在补丁发布前,loads() 函数默认启用了 secrets_from_env 功能,该功能会在反序列化时从环境变量中解析值。攻击者可以利用这一点,通过实例化一个特定的类(如 langchain_aws 中的 ChatBedrockConverse)来窃取环境变量。
这个类在实例化时会发出一个 GET 请求,其请求头中的 aws_access_key_id 值可以被攻击者通过恶意构造的数据,填充为任意指定的环境变量,从而将密钥发送到攻击者控制的服务器。
代码执行路径
默认允许列表中的 PromptTemplate 类支持使用 Jinja2 模板格式。当使用 Jinja2 渲染模板时,可以运行任意 Python 代码。虽然研究人员尚未发现直接通过 loads() 函数触发渲染的方法,但如果后续有代码调用了该反序列化对象的渲染方法,就会导致代码执行。
谁会受到影响以及如何应对
如果您的应用使用了受影响的 langchain-core 版本,且包含以下常见模式,则可能面临风险:
- 使用
astream_events(version="v1")(v1 版本使用易受攻击的序列化机制) - 使用
Runnable.astream_log() - 对不受信任的数据调用
dumps()/dumpd(),随后再调用load()/loads() - 使用
RunnableWithMessageHistory、某些缓存或从 LangChain Hub 拉取配置等内部序列化流程
最常见的攻击途径是通过大语言模型响应中的
additional_kwargs或response_metadata等字段,这些字段可以通过提示注入被控制,然后在流式操作中被序列化和反序列化。
防御指南
- 优先打补丁: 将
langchain-core升级到已修复的版本。这是降低风险最快的方法。 - 假定 LLM 输出可被操控: 将所有来自模型的输出(包括元数据、工具调用结果等)都视为不可信输入。
- 审查反序列化功能: 即使升级后,也应坚持一个原则:除非您完全信任序列化数据的来源,否则不要启用从环境变量解析密钥等危险功能。
超越 LangChain:更广泛的启示
这个漏洞是一个典型案例,揭示了一个更大的模式:
- 应用程序可能会反序列化它自认为安全生成的数据。
- 但这些数据的部分内容可能受到了不受信任来源(如提示注入)的影响。
- 一个用作内部标记的保留关键字,可能成为窃取密钥和执行代码的支点。
对于安全负责人而言,这暴露了一个令人不安的现实:大多数组织目前无法快速回答以下问题:
- 我们在哪里使用了 AI 代理?
- 生产环境中部署了哪些版本?
- 哪些服务可以访问敏感密钥?
- LLM 的输出在何处跨越了这些信任边界?
这不仅仅是开发问题,更是可见性和治理的问题。解决这类风险需要建立对 AI 系统全方位的可见性、风险评估、控制和治理能力,确保在类似的安全警报出现时,能够冷静、可控地做出响应。