CVE-2026-54656

CVE-2026-54656 is a high-severity code injection vulnerability in datamodel-code-generator (pip), affecting versions >= 0.52.1, <= 0.60.1. It is fixed in 0.60.2.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

datamodel-code-generator vulnerable to code execution on import via unescaped validators entries in --extra-template-data

When 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.

Details

Sink: src/datamodel_code_generator/model/pydantic_v2/base_model.py, _process_validators (lines 405–449, at tag 0.60.1 / commit a321547e):

def _process_validators(self) -> None:
    validators = self.extra_template_data.get("validators")
    if not validators:
        return
    ...
    for validator in validators:
        fields = validator.get("fields") or [validator.get("field")]
        fields = [f for f in fields if f]
        if not fields:
            continue
        function_path: str = validator["function"]
        function_name = function_path.rsplit(".", 1)[-1]
        mode = validator.get("mode", "after")
        fields_str = ", ".join(f"'{f}'" for f in fields)     # (A) UNESCAPED
        ...
        mode_str = f"mode='{mode}'"                          # (B) UNESCAPED
        prepared_validators.append({
            "fields_str": fields_str,
            "mode_str":   mode_str,
            "method_name": method_name,
            "function_name": function_name,
            "mode": mode,
        })
        self._additional_imports.append(Import.from_full_path(function_path))  # (C)

The strings from (A) and (B) flow verbatim into src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2:

@field_validator({{ v.fields_str }}, {{ v.mode_str }})

There is no repr() call, no identifier check, and no quote-escaping.

Secondary sink at (C): Import.from_full_path(function_path) splits on the last . and emits from <prefix> import <suffix>. A ; in function_path therefore lands in the generated import line and runs as a statement at module load.

PoC

A self-contained one-file PoC is available here: https://gist.github.com/thegr1ffyn/34d5c647e74487ffb2be27c76dace2aa

Resolution

The 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.

Submitted by: Hamza Haroon (thegr1ffyn)

Impact

Arbitrary 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:

  • Pull requests adding or modifying project-local *.template-data.json / .codegen.json files consumed by a make codegen rule or pre-commit hook.
  • Configuration snippets pasted from issue templates, READMEs, or third-party guides.
  • Multi-tenant CI systems where one tenant's config file is read by another tenant's build.

Same blast radius as GHSA-wjv6-jcfj-mf9r, but silent RCE rather than a docstring leak, significantly higher impact under the same threat model.

Introduced in 0.52.1 by commit a2b27562 (Add --validators option for Pydantic v2 field validators).

Untrusted input is evaluated as executable code within the application's runtime environment. Typical impact: arbitrary code execution within the application's privilege context.

CVE-2026-54656 has a CVSS score of 7.8 (High). The vector is requires local access, no privileges required, and user interaction required. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (0.60.2); upgrading removes the vulnerable code path.

Affected versions

datamodel-code-generator (>= 0.52.1, <= 0.60.1)

Security releases

datamodel-code-generator → 0.60.2 (pip)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Upgrade to datamodel-code-generator 0.60.2 or later.

This issue affects datamodel-code-generator versions >= 0.52.1, <= 0.60.1 and is fixed in 0.60.2.

Frequently Asked Questions

  1. What is CVE-2026-54656? CVE-2026-54656 is a high-severity code injection vulnerability in datamodel-code-generator (pip), affecting versions >= 0.52.1, <= 0.60.1. It is fixed in 0.60.2. Untrusted input is evaluated as executable code within the application's runtime environment.
  2. How severe is CVE-2026-54656? CVE-2026-54656 has a CVSS score of 7.8 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of datamodel-code-generator are affected by CVE-2026-54656? datamodel-code-generator (pip) versions >= 0.52.1, <= 0.60.1 is affected.
  4. Is there a fix for CVE-2026-54656? Yes. CVE-2026-54656 is fixed in 0.60.2. Upgrade to this version or later.
  5. Is CVE-2026-54656 exploitable, and should I be worried? Whether CVE-2026-54656 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-54656 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-54656? Upgrade datamodel-code-generator to 0.60.2 or later.

Other vulnerabilities in datamodel-code-generator

Stop the waste.
Protect your environment with Kodem.