Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

GHSA-wjv6-jcfj-mf9r is a high-severity (CVSS 7.8) Code Injection vulnerability in datamodel-code-generator. O3 Security confirms whether GHSA-wjv6-jcfj-mf9r is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.

`datamodel-code-generator` vulnerable to code injection via unescaped carriage return in `--extra-template-data` `comment` field

Also known asCVE-2026-54654PYSEC-2026-3566
Published
Jul 28, 2026
Updated
Aug 4, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Aug 4, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

EPSS Exploitation Probability

via FIRST.org ↗
0.1%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs4th percentile — riskier than 4% of all scored CVEsHighest risk
0.00%0.21%0.43%0.64%0.1%0.1%Aug 26Aug 26

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

GHSA-wjv6-jcfj-mf9r plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 0 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
🐍datamodel-code-generator

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

datamodel-code-generator is vulnerable to code injection when a developer passes an --extra-template-data file whose comment value contains a literal \r (carriage return). The comment variable is rendered into a Python # comment in six built-in templates with no line-terminator escaping. Python's tokenizer treats a bare CR as a physical-line terminator (see Python language reference — Physical lines), so the comment ends at the \r and the text after it is parsed as Python, including, when the CR is followed by suitable indentation, as a statement within the class body that follows on the next template line.

Details

The vulnerable templates each contain # {{ comment }} with no escaping:

  • src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2:12 and :19
  • src/datamodel_code_generator/model/template/TypeAliasType.jinja2:12 and :19
  • src/datamodel_code_generator/model/template/TypeStatement.jinja2:12 and :19
  • src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2:4
  • src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2:19
  • src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2:13

The pydantic_v2/BaseModel.jinja2:4 site is representative:

class {{ class_name }}({{ base_class }}):{% if comment is defined %}  # {{ comment }}{% endif %}

When the developer-supplied extras file populates comment for a model, the value reaches the template via DataModel.extra_template_data (set in src/datamodel_code_generator/model/base.py:736-742) and Jinja2 interpolates it raw. None of the templates use comment_safe, escape_docstring, or any other line-terminator filter.

PoC

Complete self contained POC is available at my secret gist: https://gist.github.com/thegr1ffyn/8ad6b8cb3cc2be9d3a0144aeb6896a3f

Impact

  • Who's affected: any developer or CI pipeline that runs datamodel-codegen --extra-template-data <file> where the extras file is influenced by attacker-controlled input. Realistic scenarios include:
    • Extras file generated from a third-party schema-annotation system.
    • Extras file vendored from an upstream repository.
    • Extras file produced by a script that merges multiple comment sources.
    • Build pipelines that template the extras file from environment variables, ticket descriptions, or commit metadata.
  • What it gains: arbitrary Python code execution in the importer's process at import time.
  • What it does NOT need: the schema itself can be entirely benign; only the extras file needs to contain the malicious comment.
  • What does block it: not passing --extra-template-data, or rejecting extras files whose comment values contain \r, \x0b, or \x0c before invocation.

Resolution

The fix normalizes comment values from built-in --extra-template-data before template rendering. Inline comments now convert CRLF, bare CR, vertical tab, and form feed into LF and prefix continuation lines with # , so attacker-controlled text stays inside the generated Python comment block.

Remediation

Upgrade to datamodel-code-generator 0.60.2 or later.

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

Submitted by: Hamza Haroon (thegr1ffyn)

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIdatamodel-code-generator0.14.1&&< 0.60.20.60.2

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for datamodel-code-generator. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update datamodel-code-generator to 0.60.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-wjv6-jcfj-mf9r is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-wjv6-jcfj-mf9r is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-wjv6-jcfj-mf9r. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Summary `datamodel-code-generator` is vulnerable to code injection when a developer passes an `--extra-template-data` file whose `comment` value contains a literal `\r` (carriage return). The `comment` variable is rendered into a Python `#` comment in six built-in templates with **no** line-terminator escaping. Python's tokenizer treats a bare CR as a physical-line terminator (see [Python language reference — Physical lines](https://docs.python.org/3/reference/lexical_analysis.html#physical-lines)), so the comment ends at the `\r` and the text after it is parsed as Python, including, when
O3 Security · Impact-Aware SCA

Is GHSA-wjv6-jcfj-mf9r in your dependencies?

O3 detects GHSA-wjv6-jcfj-mf9r across PyPI dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.

GHSA-wjv6-jcfj-mf9r: RCE (High 7.8) | O3 Security