LangChain核心库惊现致命漏洞:一个提示词就能窃取你的密钥
摘要:LangChain核心库被发现严重安全漏洞CVE-2025-68664,CVSS评分高达9.3分。该漏洞允许攻击者通过精心构造的LLM输出触发序列化注入,窃取环境变量中的敏感密钥,甚至可能执行任意代码。全球数亿次安装的LangChain应用面临风险,需立即升级至1.2.5或0.3.81版本。
圣诞节前夜,当大多数人沉浸在节日气氛中时,安全研究员却在代码中发现了一个让人背脊发凉的问题。这个被命名为”LangGrinch”的漏洞,藏身于全球最流行的AI应用框架之一——LangChain的核心代码中,已经潜伏了两年半之久。
更令人担忧的是,这不是某个边缘功能的小bug,而是框架核心序列化机制的设计缺陷。攻击者只需要一个精心构造的文本提示,就能让你的AI应用乖乖交出密钥。
这个漏洞到底有多严重?
想象一下这样的场景:你构建了一个AI客服系统,用户通过自然语言与它对话。某天,一个看似普通的提问竟然触发了一连串连锁反应,最终导致你存储在环境变量中的AWS密钥、数据库凭证,甚至API密钥,统统被悄悄发送到了攻击者的服务器上。
这听起来像是科幻电影的情节,但LangGrinch漏洞(CVE-2025-68664)让这一切成为现实。该漏洞被赋予了CVSS 9.3的严重评级,属于CWE-502类别——不受信任数据的反序列化。
受影响范围令人震惊
截至2025年12月,LangChain的下载量统计数据触目惊心:
-
总下载量:约8.47亿次(pepy.tech数据) -
最近一个月:约9800万次下载(pypistats数据) -
受影响组件:langchain-core(核心库,被所有LangChain组件依赖)
这意味着,全球范围内可能有成千上万的生产环境正在运行易受攻击的版本。从创业公司的聊天机器人,到大型企业的智能客服系统,从数据分析工具到自动化工作流,几乎所有使用LangChain构建的应用都可能暴露在风险之下。
漏洞是如何被发现的?
这个漏洞的发现过程本身就是一堂生动的安全课。Cyata公司的安全研究员并没有从复杂的攻击链开始,而是从一个简单的问题出发:
AI应用中的信任边界在哪里?开发者真的清楚这些边界吗?
在审计LangChain代码时,研究员采用了”反向工作”的方法——先找到可能造成危害的关键点(比如反序列化函数),然后倒推攻击者如何到达这些点。经过长时间的代码审计,他发现了一个令人意外的事实:
问题不在于某段”坏代码”,而在于”缺失的代码”。
LangChain的dumps()和dumpd()函数在序列化用户控制的字典时,完全没有对包含特殊标记'lc'的键进行转义处理。这个看似微小的疏忽,却打开了潘多拉的魔盒。
技术原理:一个标记键引发的灾难
LangChain的序列化机制
LangChain使用一种特殊的内部序列化格式来保存和传输对象。这个格式的核心是一个叫做'lc'的标记键——当字典中包含这个键时,LangChain会将其识别为”这是一个LangChain序列化的对象”,而不是普通的用户数据。
这种设计本身并无问题,问题在于:如何区分真正的LangChain对象和用户提供的、碰巧包含'lc'键的普通字典?
在修复前的版本中,答案是:无法区分。
攻击者的突破口
当攻击者能够控制或影响被序列化的数据(比如通过LLM的输出字段additional_kwargs或response_metadata),他们就能注入包含'lc'标记的恶意字典。当这些数据后续被反序列化时,LangChain会错误地将其当作内部对象处理,进而实例化攻击者指定的类。
让我们看一个简化的流程:
-
用户发送提示词 → AI模型处理 -
模型输出包含特殊构造的元数据 → 被序列化到日志/缓存 -
应用稍后读取并反序列化这些数据 → 触发恶意对象实例化 -
密钥被窃取或代码被执行 → 攻击完成
整个过程对终端用户和系统管理员来说完全透明,没有任何明显的异常信号。
三种主要攻击场景
根据官方安全公告,这个漏洞可以导致三种严重后果:
1. 密钥泄露:环境变量不再安全
LangChain的loads()函数支持一种特殊的secret类型,可以在反序列化时从环境变量中解析值。在修复前,secrets_from_env参数默认启用。
这意味着什么?攻击者可以构造一个序列化对象,指示系统从环境变量(比如AWS_ACCESS_KEY_ID、OPENAI_API_KEY)中读取值。如果这个值随后通过某种方式返回给攻击者——比如包含在LLM的上下文历史中——密钥就此泄露。
更隐蔽的攻击方式是利用langchain_aws包中的ChatBedrockConverse类。这个类在初始化时会发起一个HTTP GET请求,而攻击者可以:
-
控制请求的目标URL(指向攻击者的服务器) -
通过 secrets_from_env功能,将环境变量的值插入到HTTP请求头中 -
在攻击者的服务器上收集这些敏感信息
这是一次完美的盲注攻击——即使攻击者无法看到LLM的任何响应,也能成功窃取密钥。
2. 对象实例化:构造函数中的魔鬼
LangChain的反序列化函数会根据白名单检查,只允许实例化特定命名空间下的类,包括:
-
langchain_core -
langchain_openai -
langchain_aws -
langchain_anthropic -
其他生态系统包
虽然大多数类的构造函数是无害的,但总有例外。研究员发现,某些类在实例化时会触发有意义的副作用:
-
网络请求:如前面提到的 ChatBedrockConverse -
文件操作:读取或写入本地文件 -
系统调用:执行其他潜在危险的操作
这些副作用可以被精心编排,构成完整的攻击链。
3. 代码执行:Jinja2模板的后门
白名单中包含的PromptTemplate类支持多种模板格式,其中就有Jinja2。Jinja2是一个强大的模板引擎,但同时也允许在模板中执行任意Python代码。
虽然研究员没有找到仅通过loads()函数直接触发代码执行的路径,但如果反序列化后的对象在后续流程中被渲染(这在正常使用中非常常见),代码执行就会发生。
更值得注意的是,在较早的版本中,Chain类也在白名单中,而这个类具有特殊的功能,可能已经提供了通往模板渲染的直接路径。
12个易受攻击的常见场景
官方安全公告列出了12个已知的易受攻击的使用模式,这些模式在实际应用中极为常见:
实时数据流和日志场景
-
事件流(v1版本): astream_events(version="v1")使用了易受攻击的序列化方式(v2版本已修复) -
日志流: Runnable.astream_log()在流式传输日志时可能触发漏洞
序列化和反序列化操作
-
直接序列化:对不受信任的数据调用 dumps()或dumpd(),然后用load()或loads()反序列化 -
直接反序列化:用 load()或loads()处理不受信任的序列化数据
持久化和缓存场景
-
消息历史: RunnableWithMessageHistory在保存和加载对话历史时 -
向量存储: InMemoryVectorStore.load()加载向量数据时 -
各类缓存实现:在序列化和反序列化缓存内容时 -
LangChain Hub:从Hub拉取清单时( hub.pull)
其他集成场景
9-12. 公告中列出的其他组件和集成点
最关键的一点是:最常见的攻击向量来自LLM响应本身。
通过提示注入,攻击者可以影响模型输出中的additional_kwargs或response_metadata字段。这些字段在流式操作、日志记录、缓存等场景中会被序列化和反序列化,从而触发漏洞。
这正是AI安全与传统安全的交汇点——LLM的输出必须被视为不受信任的输入。如果框架将这些输出的某些部分当作结构化对象处理,攻击者就能够塑造这些内容。
如何检查你的应用是否受影响?
第一步:检查langchain-core版本
运行以下命令查看当前安装的版本:
pip show langchain-core
如果版本早于0.3.81或1.2.5,你的应用存在漏洞。
需要特别注意的是,即使你只安装了langchain或langchain-community等上层包,它们也会依赖langchain-core。务必确认实际运行环境中的版本。
第二步:审查代码中的高危模式
即使你已经更新到最新版本,也应该审查代码中是否存在以下高危模式:
高危代码特征清单:
-
使用 astream_events(version="v1")(应改用v2版本) -
调用 Runnable.astream_log() -
对可能包含用户输入或LLM输出的数据调用 dumps()/dumpd() -
使用 load()/loads()处理来自外部的序列化数据 -
从LangChain Hub拉取内容( hub.pull) -
使用消息历史、向量存储加载、缓存等功能
第三步:评估数据流路径
追踪你的应用中,哪些数据流可能包含不受信任的内容:
-
直接用户输入:聊天消息、上传的文档、API请求参数 -
LLM输出:模型生成的文本、工具调用结果、元数据字段 -
外部工具返回值:网络搜索结果、数据库查询结果、第三方API响应 -
检索的文档:从向量数据库或文档存储中检索的内容
如果这些数据在某个环节被序列化,然后在另一个环节被反序列化,就存在潜在风险。
第四步:检查secrets_from_env配置
搜索代码中所有调用load()或loads()的位置,检查是否显式设置了secrets_from_env=False。在修复前的版本中,这个参数默认为True,即使升级后,也应该明确禁用此功能,除非你完全信任序列化输入的来源。
立即采取的修复措施
紧急修复:升级到安全版本
这是降低风险最快速有效的方法。运行以下命令:
pip install --upgrade langchain-core
确保升级到的版本为:
-
0.3.81或更高版本(0.3.x系列) -
1.2.5或更高版本(1.x系列)
如果你的环境中使用了锁定文件(如requirements.txt、Pipfile.lock或poetry.lock),记得更新这些文件并在所有部署环境中同步更新。
代码级防护措施
1. 明确禁用环境变量密钥解析
在所有调用loads()的地方,显式设置:
from langchain_core.load import loads
# 即使在安全版本中,也应明确禁用
data = loads(serialized_data, secrets_from_env=False)
2. 升级事件流版本
将所有astream_events调用从v1升级到v2:
# 旧代码(易受攻击)
async for event in runnable.astream_events(input, version="v1"):
process(event)
# 新代码(安全)
async for event in runnable.astream_events(input, version="v2"):
process(event)
v2版本使用了更安全的序列化机制,不受此漏洞影响。
3. 实施输入验证
对所有可能影响序列化数据的输入进行严格验证:
-
过滤或转义包含 'lc'键的用户提供的字典 -
对LLM输出的元数据字段进行清洗 -
限制可以被序列化的字段类型和内容
4. 最小权限原则
-
不要在环境变量中存储敏感密钥,改用专用的密钥管理服务 -
运行AI应用的进程应该使用最小必需的权限 -
隔离不同信任级别的组件,避免高权限服务直接处理不受信任的输入
生产环境清单
针对生产环境,建议执行以下完整的安全审查:
部署前检查:
-
[ ] 确认所有环境(开发、测试、生产)都已升级到安全版本 -
[ ] 审查CI/CD流水线中的依赖版本 -
[ ] 更新容器镜像和虚拟机模板 -
[ ] 检查Lambda函数或其他无服务器部署的依赖
配置审查:
-
[ ] 禁用不必要的序列化功能 -
[ ] 审查所有使用 loads()的代码点 -
[ ] 确认日志和事件流配置的安全性 -
[ ] 评估缓存机制的安全性
监控和响应:
-
[ ] 设置异常反序列化行为的监控告警 -
[ ] 审查近期日志中是否有可疑的序列化活动 -
[ ] 准备应急响应计划 -
[ ] 通知相关团队和利益相关者
LangChainJS也受影响
基于同一份研究报告,LangChain的JavaScript/TypeScript版本也发现了类似的漏洞:
-
CVE编号:CVE-2025-68665 -
GitHub安全公告:GHSA-r399-636x-v7f6 -
漏洞机制:相同的 'lc'标记混淆问题
如果你的组织同时运行Python和JavaScript版本的LangChain应用,需要同时修复两个平台。这也提醒我们:基于标记的序列化、不受信任的模型输出、以及后续的反序列化,这是一个跨生态系统的反复出现的风险模式。
这个漏洞的更深层含义
LangGrinch不仅仅是”库中的一个bug”,它是一个重要的案例研究,揭示了AI应用安全的新挑战:
信任边界的模糊化
传统应用中,我们清楚地知道哪些是用户输入(不可信),哪些是系统内部数据(可信)。但在AI应用中,这条界限变得模糊:
-
LLM的输出看起来是”系统生成的”,但实际上可能受到提示注入的影响 -
工具的返回值可能来自外部API,包含不受信任的内容 -
检索的文档可能来自用户上传,嵌入恶意内容
你的应用可能在反序列化它认为是自己安全生成的数据,但这些数据实际上包含了受不受信任来源影响的字段。
单个保留键的威力
一个简单的内部标记('lc'键)成为了整个安全体系的枢纽点。当用户控制的数据碰巧包含这个标记时,整个信任模型崩溃。
这教会我们:在设计序列化格式时,必须有明确的转义机制,确保用户数据永远不会被误认为是系统结构。
AI编排层成为新的攻击面
过去两年,我们见证了大量AI应用框架的涌现。这些框架处理序列化、工具执行、缓存、追踪等”管道工作”。但这些”管道”不再只是辅助功能——它们现在是安全边界的一部分。
序列化格式、编排流水线、工具执行链,都可能成为攻击者的突破口。框架开发者和使用者都需要重新审视这些组件的安全性。
常见问题解答
我的应用只在内网运行,还需要担心吗?
需要。这个漏洞最常见的触发路径是通过LLM输出的字段,而这些字段可能受到提示注入的影响。即使你的应用不直接暴露在互联网上,只要:
-
用户可以输入提示词 -
应用会处理LLM的响应元数据 -
这些元数据会被序列化和反序列化
就存在风险。内网员工、恶意用户、甚至是无意中输入特殊内容的合法用户,都可能触发漏洞。
我使用的是LangChain的托管服务,还需要手动更新吗?
这取决于服务提供商。如果你使用的是LangSmith或其他官方托管服务,LangChain团队很可能已经在后端更新了。但是:
-
如果你自己部署了LangChain应用(即使使用了托管的LLM API),需要手动更新 -
如果你使用第三方平台运行LangChain代码,需要确认他们是否已更新 -
检查你的依赖锁定文件,确保不会在下次部署时回退到旧版本
更新后需要修改代码吗?
大多数情况下不需要。修复主要在框架内部:
-
dumps()/dumpd()现在会自动转义包含'lc'的用户字典 -
secrets_from_env的默认值改为False
但建议进行以下可选的代码改进:
-
显式设置 secrets_from_env=False以增强代码可读性 -
将 astream_events从v1升级到v2 -
添加额外的输入验证层
我能检测到正在进行的攻击吗?
直接检测很困难,因为攻击可能完全融入正常的应用行为。但可以监控以下异常信号:
-
不寻常的网络连接(特别是到未知外部服务器的请求) -
环境变量访问模式的异常 -
序列化/反序列化错误的突然增加 -
LLM响应中包含格式异常的元数据字段
设置日志记录和异常检测机制是长期安全策略的一部分。
这个漏洞会导致我的整个系统被攻破吗?
不一定,这取决于你的应用架构和权限配置:
-
最坏情况:如果你的LangChain应用运行在高权限环境中,环境变量包含关键密钥(数据库凭证、云服务密钥、私钥等),攻击者窃取这些密钥后可能获得更广泛的系统访问权限。
-
较好情况:如果你遵循了最小权限原则,使用了专门的密钥管理服务,并且应用运行在隔离环境中,影响可以被控制在较小范围。
这也是为什么纵深防御如此重要——单个漏洞不应该能够摧毁整个安全体系。
我应该暂停我的AI应用吗?
如果你已经确认在运行易受攻击的版本,建议:
立即行动场景:
-
应用处理高度敏感数据(医疗、金融、个人身份信息) -
环境变量包含关键的生产密钥 -
应用允许匿名或不受信任的用户输入
可以稍作延迟的场景:
-
内部测试或开发环境 -
低风险的演示应用 -
已经实施了额外安全控制的环境
但无论如何,更新应该是最高优先级的任务,应在数天内完成,而不是数周或数月。
LangChain团队的响应如何?
根据披露时间线,LangChain团队的响应非常迅速和专业:
-
12月4日:漏洞报告提交(通过Huntr平台) -
12月5日:LangChain维护者确认 -
12月24日:补丁发布,CVE和安全公告同步发布
从发现到修复仅用了20天,这在开源项目中是非常快的响应速度。
此外,LangChain不仅修复了具体的bug,还加强了默认配置(将secrets_from_env改为False),这显示了对安全性的重视。
这次漏洞的赏金是多少?
LangChain项目为这个发现颁发了4000美元的漏洞赏金。根据Huntr平台(LangChain运营漏洞赏金计划的平台)的记录,这是该项目有史以来授予的最高金额,之前的赏金最高为125美元。
这个数字反映了漏洞的严重性和影响范围。
面向未来:AI应用的安全治理
LangGrinch漏洞凸显了一个更大的问题:大多数组织目前无法快速、自信地回答以下问题:
-
我们在哪里使用了AI代理? -
生产环境部署了哪些版本? -
哪些服务有权访问敏感密钥? -
LLM输出在哪些地方跨越了信任边界?
这不是”开发者的问题”,而是可见性和治理的问题。
当圣诞周发布一个严重的CVE公告时,目标不应该是英雄主义的紧急响应,而应该是基于真实清单和强制性保护措施的冷静、可控的响应。
建立AI应用的可见性
成功的AI安全治理始于清晰的可见性:
-
发现所有运行AI代理的地方(IDE、CI、服务、工作任务、托管代理) -
追踪框架、包和版本的使用情况 -
识别数据流和信任边界 -
映射权限和密钥访问模式
基于风险的优先级排序
不是所有的AI应用都有相同的风险档案。需要识别:
-
哪些应用面向互联网 -
哪些应用接触敏感密钥 -
哪些应用运行在高权限环境 -
哪些应用处理不受信任的输入(结构化字段、元数据、工具输出、流式事件、缓存数据)
强制性控制和安全护栏
即使在所有依赖都完全更新之前,也可以降低暴露风险:
-
推动更安全的默认配置(最小权限、隔离边界、策略检查) -
对高风险模式设置护栏(反序列化不受信任的数据、宽松的对象恢复、不安全的流-缓存-再恢复流程) -
在不受信任的上下文中限制敏感能力(通过环境的密钥访问、高权限工具执行、在特权工作进程中运行危险代码路径)
可审计的治理流程
让”安全的AI代理使用”变得可重复、可审计、难以偏离:
-
定义批准的框架、版本和配置的策略 -
追踪例外情况,记录负责人和理由 -
监控配置漂移和高风险功能使用,保持支持安全审查和合规性的审计跟踪
最后的建议
LangGrinch是AI应用时代的一个警钟。随着AI代理框架成为关键基础设施,我们需要用同样严格的安全标准来对待它们。
对于开发者:
-
立即更新langchain-core到安全版本 -
审查你的代码中是否存在高危模式 -
将LLM输出始终视为不受信任的输入 -
实施纵深防御,不要依赖单一的安全控制
对于安全团队:
-
建立AI应用和框架使用的清单 -
制定AI安全的响应流程 -
投资于AI应用的可见性和治理工具 -
培训开发团队关于AI特有的安全风险
对于组织领导者:
-
认识到AI应用安全不是可选项 -
为安全工作分配适当的资源和优先级 -
建立跨部门的AI安全协作机制 -
在快速创新和安全之间找到平衡
这个圣诞节,安全研究员送给开源社区的礼物是一个及时的漏洞披露。现在轮到我们每个人采取行动,确保我们的AI应用不会在节日后成为攻击者的礼物。
立即检查你的LangChain版本,升级到安全版本,并审查你的安全架构。AI的未来取决于我们今天构建的安全基础。

