Severity by source
AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N
AC:H because exploitation requires the optional [http] extra plus attacker control of the URL/redirect and reachable internal services; UI:R and S:C retained, C:H from metadata/credential disclosure, I:L from reflected schema content.
Primary rating from Vendor (https://github.com/koxudaxi/datamodel-code-generator).
CVSS VectorVendor: https://github.com/koxudaxi/datamodel-code-generator
Lifecycle Timeline
3DescriptionCVE.org
Summary
datamodel-code-generator's built-in HTTP fetcher (http.get_body) issues an httpx.GET against any URL passed to --url (or reached via a redirect chain) with no allow-list, no deny-list, no IP/host validation, and follow_redirects=True. Loopback addresses, RFC1918 ranges, link-local (169.254.169.254 cloud metadata), unique-local IPv6 and any other network-accessible target are all reachable. The JSON/YAML response body is parsed as a schema and reflected into the generated .py source, exfiltrating the response to anyone with access to that file (commonly committed to a repository).
Details
Sink: src/datamodel_code_generator/http.py, get_body (lines 31-61, at tag 0.60.1 / commit a321547e):
def get_body(url, headers=None, ignore_tls=False,
query_parameters=None, timeout=DEFAULT_HTTP_TIMEOUT) -> str:
httpx = _get_httpx()
try:
response = httpx.get(
url,
headers=headers,
verify=not ignore_tls,
follow_redirects=True,
# (A)
params=query_parameters,
timeout=timeout,
)
except Exception as e:
...
if response.status_code >= 400:
...
content_type = response.headers.get("content-type", "").lower()
if "text/html" in content_type:
raise SchemaFetchError(...)
# (B) - only filter
return response.text
# (C) → embedded in generated.py- (A) follows redirects unconditionally - a public URL → 302 → internal address chain works.
- (B) the only filter is rejecting
text/html. Non-HTML internal endpoints (JSON APIs, cloud metadata, admin services) pass through. - (C) the response body becomes the schema; its
title,description,properties, etc. land in the generated.pyas class attributes andField(description=...)strings.
get_body is called by parser/base.py:1326 (_get_text_from_url), which is reached from CLI argument --url <URL>. (The $ref path is a separate advisory - see GHSA-D.)
Only affects users who installed the [http] extra (pip install 'datamodel-code-generator[http]').
PoC
A self-contained one-file PoC available here: https://gist.github.com/thegr1ffyn/18de777d6c800a3b47715425e3f3e8f5
Impact
Who is impacted. Anyone who runs datamodel-codegen with a --url they didn't fully verify, or who runs it inside a network with reachable internal services. Realistic scenarios:
- Trojan documentation / README. A blog post or README example reads
datamodel-codegen --url https://schemas.example.com/user.json -o user.py. The attacker controlsexample.com, redirects tohttp://169.254.169.254/latest/meta-data/iam/security-credentials/<role>, and the IAM credentials end up as a docstring inuser.py. - Internal port scan / disclosure. Iterating
--url http://127.0.0.1:<port>/healthprobes localhost services; non-HTML, non-error responses confirm a service and leak its body into the generated file. - CI poisoning. A PR adds a Makefile rule that calls
datamodel-codegen --url $(SCHEMA_URL); the CI runner reaches every internal service in its VPC and the response lands in PR artifacts.
Suggested fix. Resolve the URL host, reject loopback / private / link-local / multicast / reserved IPs by default, disable redirects by default (follow_redirects=False), re-validate after each redirect if the user opts into following them, and add an --allow-private-network flag for opt-in legitimate use.
Maintainer resolution
This report was fixed together with GHSA-954p-556p-r752 by the private security PR koxudaxi/datamodel-code-generator-ghsa-rfr2-mq9m-x2qx#1, 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.
The patch hardens the shared HTTP fetcher used by both direct CLI --url fetching and remote JSON Schema/OpenAPI $ref resolution:
- validates HTTP(S) URLs before fetching;
- blocks localhost, loopback, private, link-local, reserved, and other non-public network targets by default;
- disables automatic redirect following and validates each redirect target before requesting it;
- adds
--allow-private-network/allow_private_network=Trueas an explicit opt-in 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)
Articles & Coverage 2
AnalysisAI
Server-side request forgery in the datamodel-code-generator Python package (versions >= 0.9.1 and <= 0.60.2) allows an attacker who controls or influences a --url schema source to make the codegen host fetch arbitrary internal addresses - loopback, RFC1918, link-local 169.254.169.254 cloud metadata, and unique-local IPv6 - and have the response body reflected into the generated .py file as schema titles, property names, and Field(description=...) strings. The issue only affects installations that include the optional [http] extra; the fetcher applies no allow-list or IP/host validation and follows redirects unconditionally, with text/html rejection as its only filter, so non-HTML JSON/YAML endpoints (IAM credential metadata, internal admin APIs) pass through and leak into artifacts commonly committed to repositories or surfaced in CI output. Publicly available exploit code exists (a self-contained one-file PoC), but the flaw is not confirmed actively exploited (not in CISA KEV); EPSS is low at 0.21% (11th percentile), and the assessed vector (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:N, 8.2) reflects high confidentiality impact tempered by required victim interaction and AC:H.
Technical ContextAI
The root cause is CWE-918 (Server-Side Request Forgery) in src/datamodel_code_generator/http.py, function get_body (lines 31-61 at tag 0.60.1 / commit a321547e), which calls httpx.get(url, ..., follow_redirects=True) against any URL supplied via the CLI --url argument (or reached through a redirect chain) with no allow-list, deny-list, or IP/host validation. The only defensive filter is rejection of responses whose content-type contains text/html; every other content type - JSON, YAML, plain text from internal APIs and cloud metadata services - is returned as the response text. That text is then used by parser/base.py:1326 (_get_text_from_url) as the input schema, so attacker-chosen data becomes class attributes, docstrings, and Field(description=...) values in the emitted Python source. Two properties compound the risk: follow_redirects=True lets a public, attacker-controlled URL 302 the fetch to an internal target, and the absence of private/link-local IP filtering means the same code path reaches 169.254.169.254 IMDS, localhost admin services, or VPC-internal endpoints when the codegen process runs on a cloud instance or CI runner. The Python packaging ecosystem is the relevant supply-chain surface (CPE pkg:pip/datamodel-code-generator); only users who installed the [http] extra (pip install 'datamodel-code-generator[http]') are exposed, since the core install has no HTTP fetcher.
RemediationAI
Upgrade to the patched release: vendor-released patch 0.61.0 fixes this issue (with GHSA-954p-556p-r752) and hardens the shared HTTP fetcher used by both direct CLI --url fetching and remote JSON Schema/OpenAPI $ref resolution - it validates HTTP(S) URLs before fetching, blocks localhost, loopback, private, link-local, reserved, and other non-public targets by default, disables automatic redirect following, re-validates each redirect target before requesting it, and adds an explicit --allow-private-network / allow_private_network=True opt-in for trusted internal schema endpoints (installing pip install 'datamodel-code-generator[http]>=0.61.0' is sufficient). Because remote $ref fetching remains governed by --allow-remote-refs and non-public targets additionally require --allow-private-network, avoid enabling --allow-private-network in CI or shared build environments, since that reinstates the original SSRF exposure for any attacker-influenced URL. If upgrade is not immediately possible, stop invoking datamodel-codegen --url against URLs from untrusted sources such as blog posts, README examples, or PR-supplied Makefile variables, point --url only at schema hosts you control and verify the response chain does not redirect, or remove the datamodel-code-generator[http] extra so the fetcher is unavailable (trade-off: remote schema and remote $ref support is lost entirely); additionally block egress to 169.254.169.254 and RFC1918 ranges from codegen hosts and CI runners (trade-off: legitimate internal schema endpoints also become unreachable) and, on cloud instances requiring IMDS, enforce IMDSv2 with hop-limit 1 to reduce credential theft even if a fetch succeeds. Confirm the applied fix via the vendor commit https://github.com/koxudaxi/datamodel-code-generator/commit/5fdba4a09f2d7a9996a504975b7ef7d63e3715bb and the advisory at https://github.com/koxudaxi/datamodel-code-generator/security/advisories/GHSA-rfr2-mq9m-x2qx.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Same weakness CWE-918 – Server-Side Request Forgery (SSRF)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-50069
GHSA-rfr2-mq9m-x2qx