CVE-2026-54654
Improper neutralization of carriage returns in comments allows code injection.
- CVSS 7.8
- 94
- Input Validation and Sanitization
- Local
datamodel-code-generator generates Python data models from schema definitions. From 0.14.1 until 0.60.2, the –extra-template-data comment field is rendered into Python comments in src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2, src/datamodel_code_generator/model/template/TypedDict.jinja2, src/datamodel_code_generator/model/template/dataclass.jinja2, src/datamodel_code_generator/model/template/msgspec.Struct.jinja2, src/datamodel_code_generator/model/template/pydantic/BaseModel.jinja2, and src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 without neutralizing carriage returns in Python # comments, allowing an attacker-controlled comment value to inject Python code into generated models that runs when imported. This issue is fixed in version 0.60.2.
- CWE
- 94
- CVSS base score
- 7.8
- Published
- 2026-07-28
- OWASP
- A03 Injection
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Command Injection
- Accessibility scope
- Local
- Impact
- Arbitrary Code Execution
- Affected component
- datamodel-co
- Fixed by upgrading
- Yes
Solution
Upgrade `datamodel-code-generator` to version 0.60.2 or later.
Vulnerable code sample
import jinja2
def generate_model(extra_data: dict) -> str:
"""
Simulates vulnerable code generation from a Jinja2 template,
analogous to datamodel-code-generator before version 0.60.2.
"""
env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True)
template_str = """
{%- if extra_template_data.comment -%}
# {{ extra_template_data.comment }}
{%- endif -%}
class GeneratedModel:
pass
"""
template = env.from_string(template_str)
# VULNERABLE: The comment is rendered directly, allowing newline characters to break out of the comment and inject code.
return template.render(extra_template_data=extra_data)Patched code sample
import jinja2
from textwrap import indent
def generate_model(extra_data: dict) -> str:
"""
Simulates fixed code generation from a Jinja2 template,
analogous to datamodel-code-generator version 0.60.2 and later.
"""
env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True)
template_str = """
{%- if extra_template_data.comment -%}
{{ extra_template_data.comment | comment_out }}
{%- endif -%}
class GeneratedModel:
pass
"""
template = env.from_string(template_str)
# FIX: A filter is used in the template to sanitize the comment, prefixing each line with '# '.
template.environment.filters['comment_out'] = lambda s: indent(s, '# ').strip()
return template.render(extra_template_data=extra_data)Payload
owned\nimport os;os.system('id')
Cite this entry
@misc{vaitp:cve202654654,
title = {{Improper neutralization of carriage returns in comments allows code injection.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-54654},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-54654/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
