两行写死的 True,让运维显式设的 –trust-remote-code=False 静默失效,恶意模型仓库直接在推理进程里执行代码
- 主页:https://github.com/vllm-project/vllm/security/advisories/GHSA-7972-pg2x-xr59
- 从哪读起:先读 GHSA-7972-pg2x-xr59 的正文(两百多字,点名 nemotron_vl.py 与 kimi_k25.py 两个 call site),再翻 PR #36192 的 diff——改动只有两处参数替换,比任何分析文章都说明厂商修的是哪一层。
- 成名作:GHSA-7972-pg2x-xr59 / CVE-2026-27893:vLLM 0.10.1–0.17.x 的两个模型实现文件把
trust_remote_code=True写成字面量,使用户显式关闭的开关在这两条路径上无声失效,CVSS 8.8,是同一类问题在 vLLM 上的第三次复发。
两行字面量 True,和它们盖掉的那个 CLI 开关
受影响的是 vLLM 0.10.1 起、0.18.0 之前的所有版本(GHSA 给的范围),也就是从 2025 年下半年到 2026 年三月这条线上的绝大多数生产部署。问题在两个模型实现文件里:vllm/model_executor/models/nemotron_vl.py 和 vllm/model_executor/models/kimi_k25.py。GHSA 给的位置是前者第 430 行(加载 vision 子模型)与后者第 177 行(取 image processor)——我拉 v0.14.1 的 raw 文件复核时,行号对不上(工具读到的是文件靠前的位置),所以行号按官方 advisory 转述,不当作实测。
有问题的那行原样是:
return AutoModel.from_config(config.vision_config, trust_remote_code=True)
trust_remote_code 是 HuggingFace transformers 的一个参数:模型仓库里可以放一个 modeling_xxx.py,加载时 transformers 会把它 import 进来当模型定义用。设成 False 就是「我只接受 transformers 内置的架构,不 import 你仓库里的 Python」。vLLM 把它暴露成 --trust-remote-code 这个命令行开关,运维用它当安全边界。
反直觉的地方在于:这不是配置传递链断了。运维设的 False 一路正确地传到了 model_config 里,就在这两个函数手边(补丁后那行读的就是 self.model_config.trust_remote_code)。这两个 call site 只是没去读它,直接填了字面量 True。也就是说进程里同时存在两个事实——配置对象说「不信任」,实际调用说「信任」——而后者赢。
编号有两个:huntr 作为 CNA 发的 CVE-2026-4944(2026-05-28 进 NVD),GitHub 侧发的 CVE-2026-27893(2026-03-27)。两条描述与代码位置一致,指向同一处代码;两个编号是否被官方合并,我没查到声明,所以不下断言。CVSS 都是 8.8(AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H,UI:R 是因为需要运维去加载那个模型)。NVD 给 CVE-2026-4944 打的 CWE 是 CWE-22(路径穿越),这明显是错标——这里没有任何路径拼接问题,同一类的 CVE-2025-66448 被打成 CWE-94(代码生成控制不当)才是对的。NVD 页面自己也标着「Not prioritized for NVD enrichment」。
另外一个数:我本地那份 6574 篇的语料里,提到 CVE-2026-4944 的只有 1 篇——就是 CVE 条目本身。没有第三方分析进来。
从一个 config.json 到 vLLM 进程里的 shell
攻击链一共六步,RAXE 的复述与 GHSA 描述一致:
第一步,攻击者在 HuggingFace Hub 发一个模型仓库,config.json 里的 architectures 字段声明自己是 NemotronVL 或 KimiK25。仓库看起来像个正常的开源多模态模型:权重、tokenizer、README 都齐。
第二步,运维用 --trust-remote-code=False 把它拉起来——正因为不完全信任这个仓库,才特意关了这个开关。vLLM 读 config,按 architectures 分派到 nemotron_vl.py 或 kimi_k25.py。
第三步,代码走到 _init_vision_model(或 kimi 那边的 cached_get_image_processor),字面量 True 覆盖掉运维的 False。这一步没有任何输出。RAXE 的原话是「the override produces no warning, error, or audit log entry」——这句出自 RAXE-2026-044 的分析,不是官方 advisory 的措辞。
第四步,transformers 拿到 trust_remote_code=True,去读 config.json 里的 auto_map。这个字段的形状,HuggingFace 官方文档给的原样是:
"auto_map": {
"AutoConfig": "<your-repo-name>--<config-name>",
"AutoModel": "<your-repo-name>--<config-name>",
"AutoModelFor<Task>": "<your-repo-name>--<config-name>",
},
注意那个 --:它是跨仓库语法,A 仓库的 config 可以指向 B 仓库的代码。前一个 CVE-2025-66448 的攻击场景正是「发一个看起来正经的前台仓库,其 config 通过 auto_map 指向一个恶意后台仓库」。
第五步,transformers 下载那个 .py 并 import 它。import 阶段执行的是模块顶层代码——不需要等到模型 forward,不需要有人发一个推理请求,import 这个动作本身就是执行现场。
第六步,代码跑在 vLLM 主进程里,权限就是启动服务的那个用户。同一进程里有模型权重、有 KV cache、有正在飞的推理请求内容;如果这是个容器里的 GPU 节点,还有挂进来的 HF token 和内网可达性。
这里必须说清楚一件事:这个 CVE 没有公开的 PoC 仓库,恶意 modeling_*.py 的具体内容查不到。 RAXE 自己也写了,上面这些步骤「are derived from the vendor advisory description」而非动态复现。所以第五、六步的载荷我不给——网上流传的「示意性 payload」一律不是这个案子的东西。可原样引的真实内容只有两个:那行 vLLM 源码,和 HF 文档里的 auto_map JSON。
三道门,一道都没关上
第一道,--trust-remote-code=False 这个开关本身。 它对运维承诺的语义是进程级的:这台机器不执行模型仓库带的代码。实现却是逐个 call site 传参——每一个新加的模型文件、每一处调 transformers 的地方,都要自觉去读 model_config。任何一个人写新模型时图省事填个 True,这条进程级承诺就在那条路径上单方面作废,而且如上所述失效时不打日志。这不是「配置没生效」的 bug,是这个安全属性从来没有一个统一的执行点。
第二道,前两次补丁。 同一类问题这是第三次:CVE-2025-66448(2025-12-01 公开,修在 0.11.1)打的是 Nemotron_Nano_VL_Config 里解析 auto_map 时调 get_class_from_dynamic_module(),即使调用方明确传了 trust_remote_code=False 也照跑;CVE-2026-22807(影响 0.10.1–0.13.x,修在 0.14.0)打的是模型解析阶段加载 auto_map 动态模块时没有 gating。两次都修在「加载器/配置解析」那一层。而这次的两处调用在 model_executor/models/ 下面,是各个模型自己写的初始化代码——加载器那层的检查根本管不到它们。NVD 对 CVE-2026-4944 的描述里明写这是前两者的 incomplete fix。
第三道,Hub 侧的仓库信任。 名字像官方模型不等于是官方仓库;Hub 对 pickle 反序列化那类问题有扫描,但 auto_map + 自定义 modeling.py 是 transformers 的正规功能通道,一个仓库带 Python 代码本身完全合法,扫描器没有理由拦。到了 vLLM 这边,architectures 字段是攻击者自己填的——他说自己是 NemotronVL,vLLM 就按 NemotronVL 分派,正好踩进那两个文件。
还有一个不该算「防线」但常被当成防线的东西:认证。vLLM 的 API key、网关鉴权在这条链上完全不参与——代码执行发生在模型加载期,服务还没开始收请求。
补丁换了个变量名,模型仓库照样自带 Python
厂商修的是哪一层,看 PR #36192 就够了:标题 [Security] Respect user trust_remote_code setting in NemotronVL and KimiK25,作者 Russell Bryant(rbryant@redhat.com),2026-03-06 合入,commit ee89aa5b4b14bf45feda7611eee09bfe42bb3620,milestone 挂在「v0.17.0 cherry picks」,但 GHSA 标的 patched 版本是 0.18.0——我按 GHSA 为准。改动全部内容就是把两个字面量换成配置值,v0.18.0 里那行是:
return AutoModel.from_config(
config.vision_config,
trust_remote_code=self.model_config.trust_remote_code,
)
(我读的是 v0.18.0 的 raw 文件;.patch 的 URL 取不到,逐行 diff 没直接看到。)
这是把出口堵上了:这两行不会再擅自替用户 opt-in。入口一动没动,具体是三件事:
一、模型仓库可以携带任意 Python、并在 import 时执行,这个 transformers 机制照旧。补丁只是让 vLLM 在这两处不再自作主张开它。运维如果因为别的模型必须用 --trust-remote-code=True(很多多模态模型确实需要),整台机器又回到 0.10.1 时的状态。
二、依然没有进程级 kill switch。没有一个地方能让运维说「这个进程内,无论哪段代码怎么调,都不许 import 远程模块」。第四个引入自定义子组件的模型文件会是下一个入口——第三次复发就是这个模式的证据。
三、执行环境没有沙箱。代码仍旧跑在持有权重和推理数据的主进程里,不是子进程、不是受限解释器。补丁没碰这一层。
落到具体动作:升到 0.18.0;把推理进程放进单独容器并降权(不给 HF token 写权限、不给内网出口);模型来源锁死到 revision 的 commit hash 而不是 main;不要把那个 CLI flag 当成边界来做威胁建模。
还有一个没查到的数:有多少生产实例实际受影响、有没有在野利用,没有任何实测数据,公开 PoC 也不存在。
已核实来源
- https://nvd.nist.gov/vuln/detail/CVE-2026-4944
- https://github.com/vllm-project/vllm/security/advisories/GHSA-7972-pg2x-xr59
- https://github.com/advisories/GHSA-7972-pg2x-xr59
- https://github.com/vllm-project/vllm/pull/36192
- https://raxe.ai/labs/advisories/RAXE-2026-044
- https://raw.githubusercontent.com/vllm-project/vllm/v0.18.0/vllm/model_executor/models/nemotron_vl.py
- https://raw.githubusercontent.com/vllm-project/vllm/v0.14.1/vllm/model_executor/models/nemotron_vl.py
- https://huggingface.co/docs/transformers/en/custom_models
- https://nvd.nist.gov/vuln/detail/CVE-2025-66448
- https://github.com/advisories/GHSA-2pc9-4j83-qjmr
- https://huntr.com/bounties/97f706f7-a852-49b2-a4eb-76811e611daf
本文由自动化管道生成(采集 → 逐字核验 → 模型撰写),未经人工改写。