CVE-2026-54654: datamodel-code-generator Code Injection via Carriage Return in --extra-template-data comment
A carriage return character embedded in the comment field of an --extra-template-data file causes datamodel-code-generator to write executable Python code into generated model files, giving an…

The problem
datamodel-code-generator versions 0.14.1 through 0.60.1 interpolate the user-supplied comment value directly into six Jinja2 templates as a raw Python inline comment (# {{ comment }}) with no escaping of line-terminator characters.
Python's tokenizer treats a bare carriage return (\r) as a physical-line terminator, identical to a newline. So text after the \r is no longer inside the comment. If that text is valid Python and lands at the right indentation relative to the class body that follows on the next template line, it executes as a class-body statement on import.
Proof of concept
A working proof-of-concept for CVE-2026-54654 in datamodel-code-generator, with the exact payload below.
# extras.json -- supply this as: datamodel-codegen --input schema.json --extra-template-data extras.json --output out.py
{
"MyModel": {
"comment": "safe text\r __import__('os').system('id')"
}
}
# The generated out.py will contain:
class MyModel(BaseModel): # safe text
__import__('os').system('id')
field: strPython's lexical analysis treats \r (CR, 0x0D) as a physical-line terminator (see Python language reference, Physical lines). Because none of the six vulnerable templates apply any filter to the comment variable before writing # {{ comment }}, the Jinja2 render produces a literal CR in the output .py file.
The tokenizer ends the comment at the CR, and the continuation text becomes a real statement inside the class body.
The patch at commit b73abb5 normalizes the comment value before template rendering: it converts CRLF, bare CR, vertical tab (\x0b), and form feed (\x0c) to LF, then prefixes each continuation line with # so all text stays inside the comment block. The root cause is CWE-94 (Code Injection) compounded by CWE-1336 (Improper Neutralization of Special Elements Used in a Template Engine).
The fix
Upgrade to datamodel-code-generator 0.60.2 or later. The fix normalizes line-terminator characters in the comment field before Jinja2 rendering, so no attacker-controlled text can escape the # comment. If you cannot upgrade immediately, validate extras files before use and reject any comment value containing \r, \x0b, or \x0c.
Reported by Hamza Haroon (thegr1ffyn).
Related research
- high · 8.8CVE-2026-54653CVE-2026-54653: datamodel-code-generator Code Injection via default_factory Schema Field
- high · 7.8CVE-2026-54655CVE-2026-54655: datamodel-code-generator Code Injection via x-python-type
- high · 7.5CVE-2026-55415CVE-2026-55415: datamodel-code-generator Code Injection via x-python-import and customTypePath
- high · 8.2CVE-2026-54691CVE-2026-54691: datamodel-code-generator SSRF via --url