CVE-2026-48737
Published:July 09, 2026
Updated:August 27, 2026
"is_global_address" in ""src/pyload/core/utils/web/check.py"" (https://github.com/pyload/pyload/blob/1b12dc7f348db8c144e0f39215680415e90ca4d2/src/pyload/core/utils/web/check.py) is the central guard against SSRF-style outbound connections in pyload-ng. It tests whether a given IP is "globally routable" via Python's "ipaddress.ip_address(value).is_global", and callers treat "not is_global" as "deny": Python's "ipaddress.IPv6Address.is_global" classifies the NAT64 well-known prefix as globally routable on every supported Python version (3.9 through 3.14 confirmed), and on older Pythons (3.9-3.11) the 6to4 prefix as well: | address | "is_global" on Py 3.9-3.11 | "is_global" on Py 3.12+ | wrapped IPv4 | |----------------------------------|---------------------------|--------------------------|----------------------| | "2002:7f00:0001::" (6to4) | True | False | 127.0.0.1 | | "2002:0a00:0001::" (6to4) | True | False | 10.0.0.1 | | "2002:a9fe:a9fe::" (6to4) | True | False | 169.254.169.254 (IMDS)| | "64:ff9b::a9fe:a9fe" (NAT64) | True | True | 169.254.169.254 | | "64:ff9b::7f00:1" (NAT64) | True | True | 127.0.0.1 | pyload-ng declares "python_requires = >=3.9" ("setup.cfg"), so deployments on Python 3.9-3.11 see the 6to4 path too. The NAT64 path is universal. "is_global" returns True for these wrappers, so "is_global_address" returns True and the deny check passes. The pycurl "PREREQFUNC" at ""src/pyload/core/network/http/http_request.py:680"" (https://github.com/pyload/pyload/blob/1b12dc7f348db8c144e0f39215680415e90ca4d2/src/pyload/core/network/http/http_request.py#L680) consults the same helper just before TCP-connect: On a host with 6to4 routing (legacy operator tunnels; "2002::/16" still configurable) or NAT64 (cloud IPv6-only subnets with NAT64 gateway), the encoded form routes to the embedded IPv4 and the curl connection terminates at the internal endpoint, defeating the deny. "is_global_host" (the helper that callers like "parse_urls" use against a URL hostname) feeds through "host_to_ip" which pins "family=AF_INET", so hostname-based reach to these forms relies on the attacker supplying an IPv6 literal in the URL — but the curl PREREQFUNC sees the actual resolved IP (the AAAA returned for the hostname), so a hostname with an AAAA record set to one of the bypass forms reaches the same gap. Cross-reference: this is the same incomplete-coverage class as pydantic-ai's "GHSA-cqp8-fcvh-x7r3" (https://github.com/pydantic/pydantic-ai/security/advisories/GHSA-cqp8-fcvh-x7r3) / CVE-2026-46678. pyload-ng's prior SSRF advisories "GHSA-7gvf-3w72-p2pg" (https://github.com/pyload/pyload/security/advisories/GHSA-7gvf-3w72-p2pg) and "GHSA-8rp3-xc6w-5qp5" (https://github.com/pyload/pyload/security/advisories/GHSA-8rp3-xc6w-5qp5) both went through "is_global_host" / "is_global_address"; the IPv6 transition gap is orthogonal to those redirect-bypass classes.
Related Resources (5)
Do you need more information?
Contact UsCVSS v4
Base Score:
2.3
Attack Vector
NETWORK
Attack Complexity
HIGH
Attack Requirements
NONE
Privileges Required
LOW
User Interaction
NONE
Vulnerable System Confidentiality
LOW
Vulnerable System Integrity
NONE
Vulnerable System Availability
LOW
Subsequent System Confidentiality
LOW
Subsequent System Integrity
NONE
Subsequent System Availability
LOW
CVSS v3
Base Score:
4.9
Attack Vector
NETWORK
Attack Complexity
HIGH
Privileges Required
LOW
User Interaction
NONE
Scope
CHANGED
Confidentiality
LOW
Integrity
NONE
Availability
LOW
Weakness Type (CWE)
Server-Side Request Forgery (SSRF)