CVE-2026-54690: Datamodel code generator Datamodel-code-generator Vulnerable To SSRF Vulnerability

HIGH
Advisory Identifier: GHSA-954p-556p-r752
CVSS 8.2
CWE-918
Published
Advisory Summary

CVE-2026-54690 is a HIGH (CVSS 8.2) datamodel-code-generator vulnerable to ssrf vulnerability (CWE-918: Server-Side Request Forgery (SSRF)) affecting Datamodel code generator libraries in the PyPI ecosystem. The issue involves datamodel-code-generator vulnerable to ssrf via json-schema `$ref` to http url (silent by default). Remediation is available by upgrading affected packages to version 0.61.0.

CVE-2026-54690 at a Glance

CVE Identifier CVE-2026-54690
GHSA Identifier GHSA-954p-556p-r752
Severity HIGH
CVSS v3.1 Base Score 8.2
CWE Classification CWE-918: Server-Side Request Forgery (SSRF)
Affected Product Datamodel code generator
Package Ecosystem PyPI
Published Date
Last Updated

Security Impact

CVSS: 8.2

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Changed (S:C)
Confidentiality High (C:H)
Integrity Low (I:L)
Availability None (A:N)

How to Fix CVE-2026-54690

To remediate this vulnerability, upgrade all affected Datamodel code generator dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

datamodel-code-generator fixed: 0.61.0
pip install datamodel-code-generator>=0.61.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show datamodel-code-generator

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2026-54690, inspect your installed packages using pip:

pip show datamodel-code-generator

Analyze the terminal output to locate any version of Datamodel code generator in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.61.0), your application is affected.

Note: The pip show datamodel-code-generator command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-918: Server-Side Request Forgery (SSRF), where the web server receives a url or similar request from an upstream component and retrieves the contents of this url, but it does not sufficiently ensure that the request is being sent to the expected destination. In Datamodel code generator, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary JSON-Schema `$ref` values pointing at HTTP or HTTPS URLs are silently dereferenced by `datamodel-code-generator` with no IP/host validation, no scheme allow-list, and redirects followed unconditionally. The `--allow-remote-refs` gate added in 0.56.0 defaults to `None`, which only emits a deprecation warning and then fetches the URL anyway; only explicit `--allow-remote-refs=false` blocks the request. The fetched body is parsed as a sub-schema and reflected verbatim into the generated `.py` source. As a result, any JSON-Schema document the developer feeds to `datamodel-codegen` — including documents authored by an attacker — can pivot to arbitrary internal addresses and leak the response into the generated code, with no developer cooperation beyond running the tool. ### Details Sink: `src/datamodel_code_generator/parser/jsonschema.py`, `_get_ref_body` (lines 4776–4793, at tag `0.60.1` / commit `a321547e`): ```python def _get_ref_body(self, resolved_ref: str) -> dict[str, YamlValue]: if is_url(resolved_ref): if not resolved_ref.startswith("file://") and self.http_local_ref_path is None: if self.allow_remote_refs is False: raise Error(f"Fetching remote $ref is disabled: {resolved_ref}...") if self.allow_remote_refs is None: warn_deprecated( # (A) warn only "behavior.remote-ref-default", details=f"Reference: {resolved_ref}", stacklevel=2, ) return self._get_ref_body_from_url(resolved_ref) # (B) fetch fires return self._get_ref_body_from_remote(resolved_ref) ``` - (A) emits a deprecation warning when `allow_remote_refs` is its default (`None`); execution falls through to (B). - (B) routes the URL through `_get_text_from_url` → `get_body`, the same fetcher described in other report — no IP validation, redirects followed. The fetched body is then parsed as a sub-schema and merged into the model graph, so `description`, `title`, `properties`, etc. from the remote document end up in the generated `.py` source. Only affects users who installed the `[http]` extra (`pip install 'datamodel-code-generator[http]'`). ### PoC A self-contained one-file PoC is available here: https://gist.github.com/thegr1ffyn/562a6972d7dc3f2869458ae93fc608c0 ### Impact **Who is impacted.** Anyone running `datamodel-codegen` on a JSON-Schema or OpenAPI document of uncertain provenance, with the `[http]` extra installed. Real-world scenarios: 1. **Trojaned OpenAPI document.** A public REST API publishes `openapi.yaml`. One `$ref` points at `http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>`; running `datamodel-codegen` against the spec from an EC2 instance leaks the IAM credentials into the generated client. 2. **Customer-supplied JSON Schema.** A B2B SaaS auto-generates client code from customer-uploaded schemas. The customer adds an HTTP `$ref` to `http://internal-admin:8080/users.json`; the response (e.g. JSON user list) ends up in the generated Python the SaaS hands back to the customer. 3. **CI on a private network.** A PR adds `schemas/inbound.json` with an HTTP `$ref` pointed at a service reachable only from the CI cluster's VPC; the CI runner fetches it and the generated `.py` leaks the response in PR artifacts. Higher real-world risk than the sibling CLI-flag SSRF (other SSRF in this report bundle) because the *schema author* chooses the destination — the developer doesn't have to type any URL. **Suggested fix.** 1. Flip the default in `parser/base.py`: `allow_remote_refs: bool = False`, and remove the silent-fetch-with-warning fallback at `parser/jsonschema.py:4786-4791`. 2. When fetching is allowed, apply the same IP/host validation proposed for other submitted SSRF report to both the initial `$ref` URL and every redirect target. 3. Document HTTP `$ref` in a third-party schema as equivalent to running `curl` on the developer's host. ### Maintainer resolution This `$ref` report is fixed by the same shared HTTP fetcher hardening that resolved GHSA-rfr2-mq9m-x2qx. The code landed through the GHSA-rfr2 private security PR koxudaxi/datamodel-code-generator-ghsa-rfr2-mq9m-x2qx#1 and was merged into the public repository as 5fdba4a09f2d7a9996a504975b7ef7d63e3715bb. Follow-up generated-file and coverage fixes were merged in koxudaxi/datamodel-code-generator#3279 and docs were synced in #3280. The patched release is 0.61.0. No separate net code diff remains in the GHSA-954 private PR because the shared HTTP fetcher patch is already present on `main`. This advisory remains separate because the affected entry point is remote JSON Schema/OpenAPI `$ref` resolution rather than direct CLI `--url` input. The fix does not flip the `--allow-remote-refs` compatibility default in this patch. Instead, it mitigates the SSRF issue by blocking localhost, loopback, private, link-local, reserved, and other non-public network targets by default, validating every redirect target before it is fetched, and requiring `--allow-private-network` / `allow_private_network=True` for trusted internal schema endpoints. Remote `$ref` fetching remains controlled by `--allow-remote-refs`; non-public/internal targets additionally require `--allow-private-network`. Submitted by: Hamza Haroon (thegr1ffyn)

CVE-2026-54690 Affected Datamodel code generator Versions

1 component(s)
Fixed Versions:
0.61.0
Product / Package Ecosystem Affected Versions Fixed Version
datamodel-code-generator
PyPI
≥ 0.9.1
< 0.61.0
0.61.0

References

Frequently Asked Questions

What is CVE-2026-54690?
CVE-2026-54690 is a security vulnerability in Datamodel code generator involving datamodel-code-generator vulnerable to SSRF via JSON-Schema `$ref` to HTTP URL (silent by default) under CWE-918: Server-Side Request Forgery (SSRF).
Which Datamodel code generator versions are affected?
Affected versions include releases prior to 0.61.0 across affected packages: datamodel-code-generator.
What version fixes CVE-2026-54690?
Upgrading to 0.61.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is datamodel-code-generator affected?
Yes, datamodel-code-generator is affected in releases prior to 0.61.0. Upgrade your dependency to 0.61.0 or later.
What is the CVSS score of CVE-2026-54690?
CVE-2026-54690 has a CVSS v3.1 base score of 8.2 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N.
What CWE is associated with CVE-2026-54690?
CVE-2026-54690 is classified under CWE-918: Server-Side Request Forgery (SSRF) (The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.).
How can I check PyPI dependencies for CVE-2026-54690?
Run the dependency tree command: 'pip show datamodel-code-generator'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-954p-556p-r752",
  "modified" : "2026-07-28T21:42:22Z",
  "published" : "2026-07-28T21:42:22Z",
  "aliases" : [ "CVE-2026-54690" ],
  "summary" : "datamodel-code-generator vulnerable to SSRF via JSON-Schema `$ref` to HTTP URL (silent by default)",
  "details" : "### Summary\n\nJSON-Schema `$ref` values pointing at HTTP or HTTPS URLs are silently dereferenced by `datamodel-code-generator` with no IP/host validation, no scheme allow-list, and redirects followed unconditionally. The `--allow-remote-refs` gate added in 0.56.0 defaults to `None`, which only emits a deprecation warning and then fetches the URL anyway; only explicit `--allow-remote-refs=false` blocks the request. The fetched body is parsed as a sub-schema and reflected verbatim into the generated `.py` source. As a result, any JSON-Schema document the developer feeds to `datamodel-codegen` — including documents authored by an attacker — can pivot to arbitrary internal addresses and leak the response into the generated code, with no developer cooperation beyond running the tool.\n\n### Details\n\nSink: `src/datamodel_code_generator/parser/jsonschema.py`, `_get_ref_body` (lines 4776–4793, at tag `0.60.1` / commit `a321547e`):\n\n```python\ndef _get_ref_body(self, resolved_ref: str) -> dict[str, YamlValue]:\n    if is_url(resolved_ref):\n        if not resolved_ref.startswith(\"file://\") and self.http_local_ref_path is None:\n            if self.allow_remote_refs is False:\n                raise Error(f\"Fetching remote $ref is disabled: {resolved_ref}...\")\n            if self.allow_remote_refs is None:\n                warn_deprecated(                            # (A) warn only\n                    \"behavior.remote-ref-default\",\n                    details=f\"Reference: {resolved_ref}\",\n                    stacklevel=2,\n                )\n        return self._get_ref_body_from_url(resolved_ref)    # (B) fetch fires\n    return self._get_ref_body_from_remote(resolved_ref)\n```\n\n- (A) emits a deprecation warning when `allow_remote_refs` is its default (`None`); execution falls through to (B).\n- (B) routes the URL through `_get_text_from_url` → `get_body`, the same fetcher described in other report — no IP validation, redirects followed.\n\nThe fetched body is then parsed as a sub-schema and merged into the model graph, so `description`, `title`, `properties`, etc. from the remote document end up in the generated `.py` source.\n\nOnly affects users who installed the `[http]` extra (`pip install 'datamodel-code-generator[http]'`).\n\n### PoC\n\nA self-contained one-file PoC is available here: https://gist.github.com/thegr1ffyn/562a6972d7dc3f2869458ae93fc608c0\n\n### Impact\n\n**Who is impacted.** Anyone running `datamodel-codegen` on a JSON-Schema or OpenAPI document of uncertain provenance, with the `[http]` extra installed. Real-world scenarios:\n\n1. **Trojaned OpenAPI document.** A public REST API publishes `openapi.yaml`. One `$ref` points at `http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>`; running `datamodel-codegen` against the spec from an EC2 instance leaks the IAM credentials into the generated client.\n2. **Customer-supplied JSON Schema.** A B2B SaaS auto-generates client code from customer-uploaded schemas. The customer adds an HTTP `$ref` to `http://internal-admin:8080/users.json`; the response (e.g. JSON user list) ends up in the generated Python the SaaS hands back to the customer.\n3. **CI on a private network.** A PR adds `schemas/inbound.json` with an HTTP `$ref` pointed at a service reachable only from the CI cluster's VPC; the CI runner fetches it and the generated `.py` leaks the response in PR artifacts.\n\nHigher real-world risk than the sibling CLI-flag SSRF (other SSRF in this report bundle) because the *schema author* chooses the destination — the developer doesn't have to type any URL.\n\n**Suggested fix.**\n\n1. Flip the default in `parser/base.py`: `allow_remote_refs: bool = False`, and remove the silent-fetch-with-warning fallback at `parser/jsonschema.py:4786-4791`.\n2. When fetching is allowed, apply the same IP/host validation proposed for other submitted SSRF report to both the initial `$ref` URL and every redirect target.\n3. Document HTTP `$ref` in a third-party schema as equivalent to running `curl` on the developer's host.\n\n### Maintainer resolution\n\nThis `$ref` report is fixed by the same shared HTTP fetcher hardening that resolved GHSA-rfr2-mq9m-x2qx. The code landed through the GHSA-rfr2 private security PR koxudaxi/datamodel-code-generator-ghsa-rfr2-mq9m-x2qx#1 and was merged into the public repository as 5fdba4a09f2d7a9996a504975b7ef7d63e3715bb. Follow-up generated-file and coverage fixes were merged in koxudaxi/datamodel-code-generator#3279 and docs were synced in #3280. The patched release is 0.61.0.\n\nNo separate net code diff remains in the GHSA-954 private PR because the shared HTTP fetcher patch is already present on `main`. This advisory remains separate because the affected entry point is remote JSON Schema/OpenAPI `$ref` resolution rather than direct CLI `--url` input.\n\nThe fix does not flip the `--allow-remote-refs` compatibility default in this patch. Instead, it mitigates the SSRF issue by blocking localhost, loopback, private, link-local, reserved, and other non-public network targets by default, validating every redirect target before it is fetched, and requiring `--allow-private-network` / `allow_private_network=True` for trusted internal schema endpoints. Remote `$ref` fetching remains controlled by `--allow-remote-refs`; non-public/internal targets additionally require `--allow-private-network`.\n\nSubmitted by: Hamza Haroon (thegr1ffyn)",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "datamodel-code-generator"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0.9.1"
      }, {
        "fixed" : "0.61.0"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 0.60.2"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/koxudaxi/datamodel-code-generator/security/advisories/GHSA-954p-556p-r752"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/koxudaxi/datamodel-code-generator/commit/5fdba4a09f2d7a9996a504975b7ef7d63e3715bb"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/koxudaxi/datamodel-code-generator"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/koxudaxi/datamodel-code-generator/releases/tag/0.61.0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-918" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-28T21:42:22Z",
    "nvd_published_at" : null
  }
}