Advisory Database
  • Advisories
  • Dependency Scanning
  1. pypi
  2. ›
  3. pyload-ng
  4. ›
  5. CVE-2026-48737

CVE-2026-48737: pyLoad: SSRF guard bypass via IPv6 6to4/NAT64 transition wrappers of internal IPs

July 9, 2026

is_global_address in 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”:

def is_global_address(value):
try:
return ipaddress.ip_address(value).is_global
except ValueError:
return False

def is_global_host(value):
ips = host_to_ip(value)
return ips and all((is_global_address(ip) for ip in ips))

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:

addressis_global on Py 3.9-3.11is_global on Py 3.12+wrapped IPv4
2002:7f00:0001:: (6to4)TrueFalse127.0.0.1
2002:0a00:0001:: (6to4)TrueFalse10.0.0.1
2002:a9fe:a9fe:: (6to4)TrueFalse169.254.169.254 (IMDS)
64:ff9b::a9fe:a9fe (NAT64)TrueTrue169.254.169.254
64:ff9b::7f00:1 (NAT64)TrueTrue127.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 consults the same helper just before TCP-connect:

if not self.allow_private_ip:
is_proxy_ip = self.http_proxy_host and self.http_proxy_host == (conn_primary_ip, conn_primary_port)
if not is_global_address(conn_primary_ip) and not is_proxy_ip:
return pycurl.PREREQFUNC_ABORT
return pycurl.PREREQFUNC_OK

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 / CVE-2026-46678. pyload-ng’s prior SSRF advisories GHSA-7gvf-3w72-p2pg and GHSA-8rp3-xc6w-5qp5 both went through is_global_host / is_global_address; the IPv6 transition gap is orthogonal to those redirect-bypass classes.

References

  • github.com/advisories/GHSA-m5x5-28jr-gpjj
  • github.com/pyload/pyload/security/advisories/GHSA-m5x5-28jr-gpjj
  • nvd.nist.gov/vuln/detail/CVE-2026-48737

Code Behaviors & Features

Detect and mitigate CVE-2026-48737 with GitLab Dependency Scanning

Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →

Affected versions

All versions up to 0.5.0-b.3.dev100

Solution

Unfortunately, there is no solution available yet.

Impact 4.9 MEDIUM

CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:N/A:L

Learn more about CVSS

Weakness

  • CWE-918: Server-Side Request Forgery (SSRF)

Source file

pypi/pyload-ng/CVE-2026-48737.yml

Spotted a mistake? Edit the file on GitLab.

  • Site Repo
  • About GitLab
  • Terms
  • Privacy Statement
  • Contact

Page generated Sat, 08 Aug 2026 00:17:23 +0000.