被标记的模型仍进入下游代码
论文要回答一个模型扫描无法回答的问题:一个模型被公开标记为易受攻击之后,开发者是否真的停止使用它?作者追踪了 InsightDB 已标记的 16,977 个 HuggingFace 模型,并跟踪它们进入 GitHub 仓库、软件包、微调链和已部署的 HuggingFace Spaces 应用的情况。答案是标记并未阻止采用。3,757 个被标记模型(占该集合的 22.1%)至少出现在一个 GitHub 仓库中,这些引用合计 21,313 处代码出现,分布在 5,040 个不同仓库中。
这里有两个数字容易混淆。22.1% 是拥有任意代码引用的被标记模型所占比例;21,313 是代码位置的数量,它超过仓库数量,因为许多仓库引用了不止一个被标记模型。被引用最多的模型是 hf-internal-testing/tiny-random-OnnxStableDiffusionPipeline,在 350 个仓库中出现 976 次,但它是 HuggingFace 的测试模型,主要用于 CI/CD 流水线而非生产环境。排除这类测试模型后,lxyuan/distilbert-student 使用最广,在 449 个仓库中出现 594 次。
同一模型出现在四类复用面上
研究沿四个维度而非一个维度衡量暴露情况。除直接代码使用外,68 个被标记模型(0.4%)出现在产出软件包的仓库中,在 111 个仓库中产出 185 个软件包,主要是通过 GitHub Packages 分发的容器镜像。在 HuggingFace 上,3,765 个被标记模型(22.2%)声明了父模型或基础模型,其中 57 个的父模型本身也被标记,说明漏洞可以沿微调谱系被继承。反方向上,136 个被标记模型(0.8%)被用作至少一个微调子模型的基础,共产生 419 个衍生模型;其中 43 个子模型也被标记,全部子模型合计被下载 22,963 次。最后,657 个被标记模型(3.9%)至少被一个 Space 引用,在 1,239 个不同 Spaces 中形成 1,766 条模型—Space 链接,这些 Spaces 累计获得 10,837 个点赞。
这些维度并非彼此独立的人群。作者用 lxyuan/distilbert-student 展示了一个模型同时横跨全部四个维度:449 个仓库(包括成熟项目)、由该源码发布的容器镜像、82 个 Spaces,以及 24 个微调子模型。在这 24 个变体中,只有四个迁移到 SafeTensor 格式,其余保留 .bin 格式,其中若干触发了 pickle 导入警告。论文将此描述为一条可能的风险路径——不安全的检查点在运行时被反序列化,随后向终端用户提供推理结果——而不是已证实的漏洞利用。
作者如何挖掘集成模式
为了解易受攻击模型如何被接入代码,作者没有手工阅读仓库。他们构建了一条流水线,先提取代码属性图(Code Property Graph,一种记录值如何流动、控制如何分支的程序表示),再应用定制的频繁子图挖掘步骤,找出被标记模型标识符周围反复出现的结构。挖掘产生 809 个模式,经后处理缩减为 195 个极大模式,然后依据每个模式中占主导的图关系归入四类母题。
这些母题描述模型名称与消费它的 API 之间的距离和路由方式。直接使用(M1)把标识符直接传入调用,是源到汇的最短路径。局部传播(M2)先把标识符存入局部变量再转发,是分布最广的母题,覆盖 12 个框架,在 Transformers(115)、Sherpa(76)和 HF Hub(60)中支持度最高。方法传播(M3)至少跨越一个应用自定义的方法边界。条件守卫传播(M4)把使用置于分支控制逻辑之下。M1 出现在 11 个框架中,以 Transformers(121)和 HF Hub(66)为首。
安全设置被委托而非强制执行
在所有挖掘出的模式中,作者都没有发现来源验证或模型净化逻辑的证据。他们发现的是,安全决策被留给调用点参数或框架默认值,而且往往选择了宽松选项。在一个直接使用示例中,被标记的模型名与 trust_remote_code=True 一起传给 from_pretrained,Transformers 文档将该参数描述为允许在从远程仓库加载时执行任意代码;同样的共现也出现在一次 SentenceTransformer 实例化中。在 Datasets 框架中,标识符直接进入数据集加载,verification_mode 参数被省略,论文称该参数默认只对远程元数据做基本检查,跳过下载文件的完整性校验。
传播母题之所以重要,是因为它们降低了可见性。在局部传播中,标识符在到达安全敏感 API 之前变成普通局部值,因此审查者或静态工具必须重建局部数据流链,才能把汇点连回不安全来源。一个示例通过 hf_hub_download 下载被标记模型,再把得到的路径转发给 joblib.load,论文指出后者依赖 pickle,不应加载不可信文件。在 Keras 模式中,safe_mode 参数在调用点缺失,同样把决定权留给框架默认值。作者还观察到跨框架集中:各框架特有的配置最终汇聚到少量共享的检索和加载 API 上,他们认为这可能让防御方通过加固少数汇点来保护多个框架。
哪些引用真正可被利用
代码引用不等同于可利用的使用,论文把两者区分开来。对于集成语料中的 289 个模型,作者检查了引用是否与漏洞相关:237 个带有反序列化问题,59 个带有运行时问题,没有后门威胁。随后他们检查了具有适用于这些威胁的加载路径的框架,针对反序列化分析 Transformers、PyTorch 和 Ultralytics,针对运行时问题分析 Keras 和 TensorFlow。只有同时满足以下条件,引用才被计为易受攻击:模型因特定漏洞被标记,并且随后通过与该漏洞兼容的框架或格式路径加载,缺少相应防护或显式启用了不安全行为。仅获取工件而不消费模型的框架(如 huggingFace_hub)被排除在外。
这一定义划定了核心数字的边界。21,313 处代码出现衡量的是暴露,而非已确认的利用,论文自身的表述也把反序列化路径视为可能而非已证实。作者还指出,他们测得的暴露很可能只是下限,因为工件复用只有部分被记录,还可能通过配置文件、外部下载和弱元数据发生,从而避开代码级检测。
为何仅扫描模型文件不够
论文的核心论点是:警告始终附着在模型工件上,而暴露却扩散到没有任何单一视图能够连接的多个复用面上。一个因不安全反序列化被标记的模型如果从未被加载,实际风险很小;但当开发者把它传给设置了宽松选项的加载 API 时,它就变成具体威胁,作者称这在实践中很常见。由于代码引用、打包工件、衍生模型和已部署应用之间只被现有元数据或工具部分连接,传播路径只有在聚合多个互不相连的数据源时才会显现。
因此作者呼吁在应用层进行上下文感知的安全分析并设置更严格的集成护栏,而不是只对模型文件做更多扫描。他们的母题分类法是这一优先级的直接依据:它指出哪些汇点 API 在多个框架中反复出现,哪些路由模式隐藏了不安全来源,从而为应用层检查提供了具体可针对的结构。
防御方的优先级应转向何处
这项研究中最具决策意义的分界在于标记与集成之间。一个被标记但只被下载、从未被消费的模型(如被排除的仅获取类框架),与一个被直接传入加载器并带有 trust_remote_code=True 或省略 safe_mode 的模型,属于不同的风险类别。论文的证据把优先级放在调用点和各框架汇聚的共享汇点 API 上,因为挖掘出的模式正是在那里显示防护缺失或被委托给宽松默认值。22.1% 的代码引用率和 3.9% 的 Space 部署率描述被标记工件传播了多远;母题分析则描述护栏究竟能在哪里打断这种传播。
本文引用的文献
Vulnerable Models in the AI Supply Chain: An Empirical Study of Adoption, Propagation, and Usage Patterns
在 16,977 个被标记为易受攻击的 HuggingFace 模型中,3,757 个(22.1%)至少被一个 GitHub 仓库引用,在 5,040 个仓库中合计 21,313 处代码出现,而且挖掘出的集成模式中没有一个显示来源验证或模型净化逻辑。
