Open-Source Security Intelligence

Know every vulnerability
before it knows you.

DevGuard continuously monitors your dependencies and alerts you when CVEs like this one affect your stack — with real-time threat intelligence built for developers.

Search

GHSA-rfr2-mq9m-x2qx

HighCVSS 8.2 / 10
Published Jul 28, 2026·Last modified Jul 28, 2026
Affected Components(0)

No affected components available

Description

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 .py as class attributes and Field(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:

  1. Trojan documentation / README. A blog post or README example reads datamodel-codegen --url https://schemas.example.com/user.json -o user.py. The attacker controls example.com, redirects to http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>, and the IAM credentials end up as a docstring in user.py.
  2. Internal port scan / disclosure. Iterating --url http://127.0.0.1:<port>/health probes localhost services; non-HTML, non-error responses confirm a service and leak its body into the generated file.
  3. 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=True as 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)

Risk Scores
Base Score
8.2

The vulnerability can be exploited over the network without needing physical access. It is easy for an attacker to exploit this vulnerability. An attacker does not need any special privileges or access rights. The attacker needs the user to perform some action, like clicking a link. The vulnerability can affect other systems as well, not just the initial system. There is a high impact on the confidentiality of the information. There is a low impact on the integrity of the data.

Threat Intelligence
7.5

Exploitation activity has been observed. Apply available patches or mitigations urgently.

EPSS
0.21%

The exploit probability is very low. The vulnerability is unlikely to be exploited in the next 30 days.

Exploit
Not available

We did not find any exploit available. Neither in GitHub repositories nor in the Exploit-Database.

Browse More

Scan your project

Continuously monitor your dependencies and get alerted when vulnerabilities like this one affect your stack.

Checkout DevGuard