{"id":"CVE-2026-54656","aliases":["EUVD-2026-50075","GHSA-8m8r-38jm-f355","PYSEC-2026-3559"],"status":"published","title":"`datamodel-code-generator` vulnerable to code execution on import via unescaped `validators` entries in --extra-template-data","description":"datamodel-code-generator generates Pydantic v2 models, dataclasses, TypedDict, and msgspec.Struct from OpenAPI, JSON Schema, GraphQL, Avro, Protobuf, and raw JSON, YAML, or CSV. From 0.52.1 until 0.60.2, datamodel-code-generator interpolates validators from --extra-template-data in src/datamodel_code_generator/model/pydantic_v2/base_model.py through _process_validators into @field_validator decorators without safe validation, allowing Python code execution when the generated Pydantic v2 model is imported. This issue is fixed in version 0.60.2.","severity":{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00252,"percentile":0.16817,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-94"],"published":"2026-07-28T21:43:56Z","modified":"2026-10-28T02:30:24Z","fixes":[{"ecosystem":"PyPI","package":"datamodel-code-generator","fixed_in":["0.60.2"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"datamodel-code-generator","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.52.1"},{"last_affected":"0.60.1"},{"fixed":"0.60.2"}]}]},{"source":"osv","ecosystem":"PyPI","package":"datamodel-code-generator","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.52.1"},{"fixed":"0.60.2"}]}],"versions":["0.52.1","0.52.2","0.53.0","0.54.0","0.54.1","0.55.0","0.56.0","0.56.1","0.57.0","0.58.0","0.59.0","0.59.1","0.60.0","0.60.1"]},{"source":"osv","ecosystem":"PyPI","package":"datamodel-code-generator","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.52.1"},{"fixed":"0.60.2"}]}],"versions":["0.52.1","0.52.2","0.53.0","0.54.0","0.54.1","0.55.0","0.56.0","0.56.1","0.57.0","0.58.0","0.59.0","0.59.1","0.60.0","0.60.1"]}],"products":[{"vendor":"koxudaxi","product":"datamodel-code-generator"}],"references":[{"url":"https://github.com/koxudaxi/datamodel-code-generator/security/advisories/GHSA-8m8r-38jm-f355","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/koxudaxi/datamodel-code-generator/commit/a43d02906111a2fdcaf13ee5b62eb2da85376f19","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/koxudaxi/datamodel-code-generator/releases/tag/0.60.2","tags":["x_refsource_MISC","Release Notes","web"]},{"url":"https://github.com/advisories/GHSA-8m8r-38jm-f355","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/54xxx/CVE-2026-54656.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-54656","tags":["advisory"]},{"url":"https://github.com/koxudaxi/datamodel-code-generator","tags":["package"]},{"url":"https://pypi.org/project/datamodel-code-generator","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-54656","title":"`datamodel-code-generator` vulnerable to code execution on import via unescaped `validators` entries in --extra-template-data","description":"datamodel-code-generator generates Pydantic v2 models, dataclasses, TypedDict, and msgspec.Struct from OpenAPI, JSON Schema, GraphQL, Avro, Protobuf, and raw JSON, YAML, or CSV. From 0.52.1 until 0.60.2, datamodel-code-generator interpolates validators from --extra-template-data in src/datamodel_code_generator/model/pydantic_v2/base_model.py through _process_validators into @field_validator decorators without safe validation, allowing Python code execution when the generated Pydantic v2 model is imported. This issue is fixed in version 0.60.2.","status":"published","published":"2026-07-28T21:43:56.286Z","modified":"2026-07-29T14:12:17.588Z","cvss":[{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T13:38:09.774038Z"}],"euvd":[{"id":"EUVD-2026-50075","description":"datamodel-code-generator generates Pydantic v2 models, dataclasses, TypedDict, and msgspec.Struct from OpenAPI, JSON Schema, GraphQL, Avro, Protobuf, and raw JSON, YAML, or CSV. From 0.52.1 until 0.60.2, datamodel-code-generator interpolates validators from --extra-template-data in src/datamodel_code_generator/model/pydantic_v2/base_model.py through _process_validators into @field_validator decorators without safe validation, allowing Python code execution when the generated Pydantic v2 model is imported. This issue is fixed in version 0.60.2.","status":"published","published":"2026-07-28T21:43:56Z","modified":"2026-07-29T14:12:17Z","cvss":[{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T18:02:30.152277Z"}],"ghsa":[{"id":"GHSA-8m8r-38jm-f355","title":"`datamodel-code-generator` vulnerable to code execution on import via unescaped `validators` entries in --extra-template-data","description":"### Summary\n\nWhen the Pydantic v2 output mode is in use, `datamodel-code-generator` reads a `validators` array from each model entry in the `--extra-template-data` file and synthesises a Pydantic `@field_validator(...)` decorator from each entry. The field names and the validator mode are interpolated into the decorator call wrapped in *unescaped* single quotes. A value containing `'` breaks out of the string literal, letting an attacker emit an arbitrary positional Python expression into the decorator. The expression is evaluated at class-definition time, i.e. the moment the developer imports the generated module. This is the same trust model as the recently-published GHSA-wjv6-jcfj-mf9r (extras-file comment injection) but the impact is full RCE rather than a docstring leak.\n\n### Details\n\nSink: `src/datamodel_code_generator/model/pydantic_v2/base_model.py`, `_process_validators` (lines 405–449, at tag `0.60.1` / commit `a321547e`):\n\n```python\ndef _process_validators(self) -\u003e None:\n    validators = self.extra_template_data.get(\"validators\")\n    if not validators:\n        return\n    ...\n    for validator in validators:\n        fields = validator.get(\"fields\") or [validator.get(\"field\")]\n        fields = [f for f in fields if f]\n        if not fields:\n            continue\n        function_path: str = validator[\"function\"]\n        function_name = function_path.rsplit(\".\", 1)[-1]\n        mode = validator.get(\"mode\", \"after\")\n        fields_str = \", \".join(f\"'{f}'\" for f in fields)     # (A) UNESCAPED\n        ...\n        mode_str = f\"mode='{mode}'\"                          # (B) UNESCAPED\n        prepared_validators.append({\n            \"fields_str\": fields_str,\n            \"mode_str\":   mode_str,\n            \"method_name\": method_name,\n            \"function_name\": function_name,\n            \"mode\": mode,\n        })\n        self._additional_imports.append(Import.from_full_path(function_path))  # (C)\n```\n\nThe strings from (A) and (B) flow verbatim into `src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2`:\n\n```jinja\n@field_validator({{ v.fields_str }}, {{ v.mode_str }})\n```\n\nThere is no `repr()` call, no identifier check, and no quote-escaping.\n\nSecondary sink at (C): `Import.from_full_path(function_path)` splits on the last `.` and emits `from \u003cprefix\u003e import \u003csuffix\u003e`. A `;` in `function_path` therefore lands in the generated import line and runs as a statement at module load.\n\n### PoC\n\nA self-contained one-file PoC is available here: https://gist.github.com/thegr1ffyn/34d5c647e74487ffb2be27c76dace2aa\n\n### Impact\n\nArbitrary code execution in the developer's interpreter / CI runner the moment the generated module is imported. Anyone who accepts a `--extra-template-data` file from an untrusted source is impacted:\n\n- Pull requests adding or modifying project-local `*.template-data.json` / `.codegen.json` files consumed by a `make codegen` rule or pre-commit hook.\n- Configuration snippets pasted from issue templates, READMEs, or third-party guides.\n- Multi-tenant CI systems where one tenant's config file is read by another tenant's build.\n\nSame blast radius as GHSA-wjv6-jcfj-mf9r, but silent RCE rather than a docstring leak — significantly higher impact under the same threat model.\n\n\n \n\u003e Introduced in 0.52.1 by commit [`a2b27562`](https://github.com/koxudaxi/datamodel-code-generator/commit/a2b27562) (*Add --validators option for Pydantic v2 field validators*).\n\n### Resolution\n\nThe fix validates `validators` entries with Pydantic models before rendering them. Field names must be valid non-keyword Python identifiers, `function` must be a dotted Python identifier path, and `mode` must be one of Pydantic's supported validator modes. The generated decorator arguments now render field names with `repr()` and mode with `!r`, so validated values are still emitted as Python string literals.\n\n### Remediation\n\nUpgrade to `datamodel-code-generator` `0.60.2` or later.\n\nThis issue affects `datamodel-code-generator` versions `\u003e= 0.52.1, \u003c= 0.60.1` and is fixed in `0.60.2`.\n\nSubmitted by: Hamza Haroon (thegr1ffyn)","status":"published","published":"2026-07-28T21:44:09Z","modified":"2026-07-28T21:44:10Z","cvss":[{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:40:53.707378Z"}],"nvd":[{"id":"CVE-2026-54656","description":"datamodel-code-generator generates Pydantic v2 models, dataclasses, TypedDict, and msgspec.Struct from OpenAPI, JSON Schema, GraphQL, Avro, Protobuf, and raw JSON, YAML, or CSV. From 0.52.1 until 0.60.2, datamodel-code-generator interpolates validators from --extra-template-data in src/datamodel_code_generator/model/pydantic_v2/base_model.py through _process_validators into @field_validator decorators without safe validation, allowing Python code execution when the generated Pydantic v2 model is imported. This issue is fixed in version 0.60.2.","status":"published","published":"2026-07-28T22:17:40.507Z","modified":"2026-10-23T23:10:00.157Z","cvss":[{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:12:33.629616Z"}],"osv":[{"id":"CVE-2026-54656","title":"`datamodel-code-generator` vulnerable to code execution on import via unescaped `validators` entries in --extra-template-data","description":"datamodel-code-generator generates Pydantic v2 models, dataclasses, TypedDict, and msgspec.Struct from OpenAPI, JSON Schema, GraphQL, Avro, Protobuf, and raw JSON, YAML, or CSV. From 0.52.1 until 0.60.2, datamodel-code-generator interpolates validators from --extra-template-data in src/datamodel_code_generator/model/pydantic_v2/base_model.py through _process_validators into @field_validator decorators without safe validation, allowing Python code execution when the generated Pydantic v2 model is imported. This issue is fixed in version 0.60.2.","status":"published","published":"2026-07-28T21:43:56.286Z","modified":"2026-10-28T02:30:24.172587593Z","cvss":[{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T15:45:10.818486Z"},{"id":"GHSA-8m8r-38jm-f355","title":"`datamodel-code-generator` vulnerable to code execution on import via unescaped `validators` entries in --extra-template-data","description":"### Summary\n\nWhen the Pydantic v2 output mode is in use, `datamodel-code-generator` reads a `validators` array from each model entry in the `--extra-template-data` file and synthesises a Pydantic `@field_validator(...)` decorator from each entry. The field names and the validator mode are interpolated into the decorator call wrapped in *unescaped* single quotes. A value containing `'` breaks out of the string literal, letting an attacker emit an arbitrary positional Python expression into the decorator. The expression is evaluated at class-definition time, i.e. the moment the developer imports the generated module. This is the same trust model as the recently-published GHSA-wjv6-jcfj-mf9r (extras-file comment injection) but the impact is full RCE rather than a docstring leak.\n\n### Details\n\nSink: `src/datamodel_code_generator/model/pydantic_v2/base_model.py`, `_process_validators` (lines 405–449, at tag `0.60.1` / commit `a321547e`):\n\n```python\ndef _process_validators(self) -\u003e None:\n    validators = self.extra_template_data.get(\"validators\")\n    if not validators:\n        return\n    ...\n    for validator in validators:\n        fields = validator.get(\"fields\") or [validator.get(\"field\")]\n        fields = [f for f in fields if f]\n        if not fields:\n            continue\n        function_path: str = validator[\"function\"]\n        function_name = function_path.rsplit(\".\", 1)[-1]\n        mode = validator.get(\"mode\", \"after\")\n        fields_str = \", \".join(f\"'{f}'\" for f in fields)     # (A) UNESCAPED\n        ...\n        mode_str = f\"mode='{mode}'\"                          # (B) UNESCAPED\n        prepared_validators.append({\n            \"fields_str\": fields_str,\n            \"mode_str\":   mode_str,\n            \"method_name\": method_name,\n            \"function_name\": function_name,\n            \"mode\": mode,\n        })\n        self._additional_imports.append(Import.from_full_path(function_path))  # (C)\n```\n\nThe strings from (A) and (B) flow verbatim into `src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2`:\n\n```jinja\n@field_validator({{ v.fields_str }}, {{ v.mode_str }})\n```\n\nThere is no `repr()` call, no identifier check, and no quote-escaping.\n\nSecondary sink at (C): `Import.from_full_path(function_path)` splits on the last `.` and emits `from \u003cprefix\u003e import \u003csuffix\u003e`. A `;` in `function_path` therefore lands in the generated import line and runs as a statement at module load.\n\n### PoC\n\nA self-contained one-file PoC is available here: https://gist.github.com/thegr1ffyn/34d5c647e74487ffb2be27c76dace2aa\n\n### Impact\n\nArbitrary code execution in the developer's interpreter / CI runner the moment the generated module is imported. Anyone who accepts a `--extra-template-data` file from an untrusted source is impacted:\n\n- Pull requests adding or modifying project-local `*.template-data.json` / `.codegen.json` files consumed by a `make codegen` rule or pre-commit hook.\n- Configuration snippets pasted from issue templates, READMEs, or third-party guides.\n- Multi-tenant CI systems where one tenant's config file is read by another tenant's build.\n\nSame blast radius as GHSA-wjv6-jcfj-mf9r, but silent RCE rather than a docstring leak — significantly higher impact under the same threat model.\n\n\n \n\u003e Introduced in 0.52.1 by commit [`a2b27562`](https://github.com/koxudaxi/datamodel-code-generator/commit/a2b27562) (*Add --validators option for Pydantic v2 field validators*).\n\n### Resolution\n\nThe fix validates `validators` entries with Pydantic models before rendering them. Field names must be valid non-keyword Python identifiers, `function` must be a dotted Python identifier path, and `mode` must be one of Pydantic's supported validator modes. The generated decorator arguments now render field names with `repr()` and mode with `!r`, so validated values are still emitted as Python string literals.\n\n### Remediation\n\nUpgrade to `datamodel-code-generator` `0.60.2` or later.\n\nThis issue affects `datamodel-code-generator` versions `\u003e= 0.52.1, \u003c= 0.60.1` and is fixed in `0.60.2`.\n\nSubmitted by: Hamza Haroon (thegr1ffyn)","status":"published","published":"2026-07-28T21:44:09Z","modified":"2026-08-04T14:40:45.15561732Z","cvss":[{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T15:46:42.437513Z"},{"id":"PYSEC-2026-3559","title":"`datamodel-code-generator` vulnerable to code execution on import via unescaped `validators` entries in --extra-template-data","description":"### Summary\n\nWhen the Pydantic v2 output mode is in use, `datamodel-code-generator` reads a `validators` array from each model entry in the `--extra-template-data` file and synthesises a Pydantic `@field_validator(...)` decorator from each entry. The field names and the validator mode are interpolated into the decorator call wrapped in *unescaped* single quotes. A value containing `'` breaks out of the string literal, letting an attacker emit an arbitrary positional Python expression into the decorator. The expression is evaluated at class-definition time, i.e. the moment the developer imports the generated module. This is the same trust model as the recently-published GHSA-wjv6-jcfj-mf9r (extras-file comment injection) but the impact is full RCE rather than a docstring leak.\n\n### Details\n\nSink: `src/datamodel_code_generator/model/pydantic_v2/base_model.py`, `_process_validators` (lines 405–449, at tag `0.60.1` / commit `a321547e`):\n\n```python\ndef _process_validators(self) -\u003e None:\n    validators = self.extra_template_data.get(\"validators\")\n    if not validators:\n        return\n    ...\n    for validator in validators:\n        fields = validator.get(\"fields\") or [validator.get(\"field\")]\n        fields = [f for f in fields if f]\n        if not fields:\n            continue\n        function_path: str = validator[\"function\"]\n        function_name = function_path.rsplit(\".\", 1)[-1]\n        mode = validator.get(\"mode\", \"after\")\n        fields_str = \", \".join(f\"'{f}'\" for f in fields)     # (A) UNESCAPED\n        ...\n        mode_str = f\"mode='{mode}'\"                          # (B) UNESCAPED\n        prepared_validators.append({\n            \"fields_str\": fields_str,\n            \"mode_str\":   mode_str,\n            \"method_name\": method_name,\n            \"function_name\": function_name,\n            \"mode\": mode,\n        })\n        self._additional_imports.append(Import.from_full_path(function_path))  # (C)\n```\n\nThe strings from (A) and (B) flow verbatim into `src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2`:\n\n```jinja\n@field_validator({{ v.fields_str }}, {{ v.mode_str }})\n```\n\nThere is no `repr()` call, no identifier check, and no quote-escaping.\n\nSecondary sink at (C): `Import.from_full_path(function_path)` splits on the last `.` and emits `from \u003cprefix\u003e import \u003csuffix\u003e`. A `;` in `function_path` therefore lands in the generated import line and runs as a statement at module load.\n\n### PoC\n\nA self-contained one-file PoC is available here: https://gist.github.com/thegr1ffyn/34d5c647e74487ffb2be27c76dace2aa\n\n### Impact\n\nArbitrary code execution in the developer's interpreter / CI runner the moment the generated module is imported. Anyone who accepts a `--extra-template-data` file from an untrusted source is impacted:\n\n- Pull requests adding or modifying project-local `*.template-data.json` / `.codegen.json` files consumed by a `make codegen` rule or pre-commit hook.\n- Configuration snippets pasted from issue templates, READMEs, or third-party guides.\n- Multi-tenant CI systems where one tenant's config file is read by another tenant's build.\n\nSame blast radius as GHSA-wjv6-jcfj-mf9r, but silent RCE rather than a docstring leak — significantly higher impact under the same threat model.\n\n\n \n\u003e Introduced in 0.52.1 by commit [`a2b27562`](https://github.com/koxudaxi/datamodel-code-generator/commit/a2b27562) (*Add --validators option for Pydantic v2 field validators*).\n\n### Resolution\n\nThe fix validates `validators` entries with Pydantic models before rendering them. Field names must be valid non-keyword Python identifiers, `function` must be a dotted Python identifier path, and `mode` must be one of Pydantic's supported validator modes. The generated decorator arguments now render field names with `repr()` and mode with `!r`, so validated values are still emitted as Python string literals.\n\n### Remediation\n\nUpgrade to `datamodel-code-generator` `0.60.2` or later.\n\nThis issue affects `datamodel-code-generator` versions `\u003e= 0.52.1, \u003c= 0.60.1` and is fixed in `0.60.2`.\n\nSubmitted by: Hamza Haroon (thegr1ffyn)","status":"published","published":"2026-08-04T11:34:44.49764Z","modified":"2026-08-04T14:30:14.930466141Z","cvss":[{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:52:56.847083Z"}]}}
