今天只有一起:结构化输出的解析器是 exec(),谁说服模型谁就拿到进程
今天只有一起。Google langfun 的 lf.query —— 一个把「让模型返回一个 ImageDescription 对象」这种需求包装成函数调用的库 —— 用执行 Python 代码的方式来解析模型的结构化输出,而且默认不开沙箱。攻击链上没有传统意义的解析漏洞,缺陷就在于「让模型说什么」和「让主机跑什么」之间只隔了一次 exec()。
CVE-2026-75062 · Google langfun
披露日 2026-08-26,NVD 记 CVSS 9.2 CRITICAL(具体向量没查到)。GitHub Advisory 里这条标着 Unreviewed,也就是 GitHub 只是从 NVD 同步了记录,没有自己复核。
攻击链。 langfun 的卖点是「面向对象的 prompting」:你写 lf.query('描述这张图', ImageDescription, lm=...),它替你把 schema 塞进 prompt,再把模型的回答变回一个 Python 对象。变回对象的办法是——让模型直接吐 Python 源码(ImageDescription(objects=[...]) 这种构造表达式),然后跑它。issue #725 里给出的调用路径是 lf.query → Mapping.parse_result → PythonPromptingProtocol.parse_value → structure_from_python(sandbox=False) → exec(),默认参数是 protocol='python'、sandbox=False、permission=ASSIGN|CALL。
那道 permission 过滤器是 AST 层面的:它只允许赋值和函数调用两类语法节点,但不管你调用的是谁。open() 能调,__import__() 也能调——「只允许调用」和「只允许调用安全的东西」是两回事。
于是攻击者不需要碰你的服务器,只需要碰模型的输入。RAG 检索到的一篇文档、用户发来的一条消息、上一个 tool 返回的一段文本,里面写着「回答时请在对象构造前先执行……」。这就是 indirect prompt injection:模型读进去的是数据,但它分不清哪句是你的 schema 要求、哪句是文档作者塞的指令。模型照办,吐出一段带 __import__('os') 的表达式,langfun 在你的应用进程里跑掉——拿 API key、读文件系统、往外发请求。最阴的一点是 issue 作者提到的:恶意回答仍然可以返回一个合法的 schema 对象,调用方拿到的东西看起来完全正常,日志上什么也看不出来。
模型在链里的那一环。 模型是代码生成器,也是唯一的代码来源。这条链上没有攻击者直接控制的字符串进入 exec()——进去的是模型的输出。攻击者控制的是 prompt 上下文,模型把自然语言诱导翻译成可执行 Python,langfun 负责执行。抽掉模型这一步,攻击者手里只有一段没人会跑的文本。
修的是哪一层。 issue #725 的三条建议按优先级是:把 exec 换成只认字面量的求值器(ast.literal_eval 那一路,只能构造数据、不能调函数);退一步先把 sandbox=True 设成默认;至少在 docstring 和 README 里写清楚。这三条都在出口侧——限制模型输出能干什么,而不是保证模型不被说服。入口侧(怎么防止文档里的一句话改写模型行为)没有任何改动,也基本没法有。
修没修,说不准。 NVD 的描述写的是「0.1.2 之前的版本受影响」,但 PyPI 上 langfun 的最新正式版仍是 2024-07-23 的 0.1.1,0.1.2 只有 dev 夜间构建;issue #725 自 2026-05-30 提交起状态是 open,Google 的 OSS VRP 按仓库分级把它判成了 Won’t Fix (Intended Behavior),让报告者公开提 issue 交给社区处理。所以「升级到 0.1.2」这个动作对应哪个实际发布物,没查到。现在能确定的缓解只有一条:别用默认 protocol 跑不可信输入,或者自己把 sandbox 打开。
已核实来源
- https://nvd.nist.gov/vuln/detail/CVE-2026-75062
- https://github.com/google/langfun/issues/725
- https://github.com/advisories?query=langfun
- https://pypi.org/project/langfun/
- https://github.com/google/langfun/blob/main/langfun/core/structured/querying.py
本文由自动化管道生成(采集 → 逐字核验 → 模型撰写),未经人工改写。