CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-m34r-v34r-rf9q: `datamodel-code-generator` vulnerable to code execution on import via `x-python-type` JSON-Schema extension in datamodel-code-generator

highCVSS 7.8CVE-2026-54655
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

Source
GitHub Security Advisories (INTL · database · site)
Severity
high — CVSS 7.8
Published
2026-07-28
Last updated
2026-07-28
Exploitation
Not in CISA KEV at last sync

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.

Referenced CVEs

CVECSIRTS overviewExternal
CVE-2026-54655coverage & exploitation statusNVD · CVE.org

Same CVEs, other sources

How other CERTs, PSIRTs and databases cover the vulnerabilities in this advisory.

More from GitHub Security Advisories