GHSA-m34r-v34r-rf9q: `datamodel-code-generator` vulnerable to code execution on import via `x-python-type` JSON-Schema extension in datamodel-code-generator
Summary
datamodel-code-generator honours a custom x-python-type JSON-Schema extension that lets a schema author override the generated Python type for a field. The value is forwarded verbatim into the generated Python source as the field annotation, with a single sanitisation pass that is trivial to bypass. An attacker who controls a JSON Schema fed to datamodel-codegen can therefore embed an arbitrary Python statement in the generated module, which executes at class-definition time the moment the developer imports the file. No --extra-template-data and no special flags are required; the vulnerable code is reachable with default settings.
Details
Sink: src/datamodel_code_generator/parser/jsonschema.py, _get_python_type_override (lines 2055–2096, at tag 0.60.1 / commit a321547e):
def _get_python_type_override(self, obj: JsonSchemaObject) -> DataType | None:
x_python_type = obj.extras.get("x-python-type")
if not x_python_type or not isinstance(x_python_type, str):
return None
schema_type = obj.type if isinstance(obj.type, str) else None
if self._is_compatible_python_type(schema_type, x_python_type):
return None
base_type = self._get_python_type_base(x_python_type)
import_ = self._resolve_type_import(base_type)
type_str = x_python_type
prefix = x_python_type.split("[", maxsplit=1)[0]
if "." in prefix: # only sanitiser
type_str = base_type + x_python_type[len(prefix):]
...
...
result = self.data_type(type=type_str, import_=import_)
...
return result
DataType.type flows unescaped into {{ field.type_hint }} in every model template
(model/template/pydantic_v2/BaseModel.jinja2,
model/template/dataclass.jinja2,
model/template/TypedDictClass.jinja2,
model/template/msgspec.jinja2, …).
The only sanitiser — the dot-rewrite at the marked line — fires only when . is in the substring before the first [ in the value. Placing [ early (e.g. X[1]; <payload>) keeps prefix == "X" so the rewrite is skipped and the whole value lands in the generated annotation.
from future import anno
Details
Original advisory: https://github.com/advisories/GHSA-m34r-v34r-rf9q
Exploitation outlook
EPSS (FIRST.org) estimates each CVE’s probability of exploitation in the next 30 days — here is the CSIRTS.com read on those numbers.
- Low exploitation riskCVE-2026-546550.14% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 4% of all scored CVEs.
Referenced CVEs
| CVE | CSIRTS overview | External |
|---|---|---|
| CVE-2026-54655 | coverage & exploitation status | NVD · CVE.org |
Same CVEs, other sources
How other CERTs, PSIRTs and databases cover the vulnerabilities in this advisory.
More from GitHub Security Advisories
- mediumGHSA-jr6p-8pjj-mfx6: Capsule has an incomplete fix of CVE-2026-22872: TenantResource RawItems and Generators s…2026-07-31
- mediumGHSA-68cj-mvg9-rgm2: Capsule: CapsuleConfiguration NodeMetadata regex fields lack webhook validation, allowing…2026-07-31
- mediumGHSA-ff84-5f28-78qj: re2: Out-of-bounds heap read in `exec`/`test`/`match` via attacker-influenced `lastIndex`…2026-07-31
- mediumGHSA-6hxr-mr5r-9836: re2: Global `String.prototype.match` with an empty-matchable pattern never advances → inf…2026-07-31
- mediumGHSA-x83g-979r-f5fh: Sylius Mollie Plugin has unauthenticated IDOR that leaks order token and customer PII2026-07-31