SSRF

SSRF in Django: InvenTree CVE-2026-39362 [CVE-2026-39362]

[Updated November 2026] Updated CVE-2026-39362

Overview

The CVE-2026-39362 entry describes an SSRF vulnerability in InvenTree where authenticated users could supply remote_image URLs that are fetched server-side using requests.get(), with only Django's URLValidator guarding the input. Because the validation did not disallow private IP ranges or internal hostnames and redirects were followed, an attacker could cause the server to reach internal services, cloud meta endpoints, or other protected resources. This is a classic SSRF scenario where user-controlled URLs become a conduit for internal network access, data exfiltration, or internal reconnaissance, all under the purview of an authenticated user. In practice, an attacker could pass URLs like http://localhost, http://127.0.0.1, or http://169.254.169.254/ to trigger internal fetches when the code uses requests.get() after a permissive URL format check. The presence of allow_redirects=True meant any redirects could be followed to an internal or otherwise restricted endpoint, bypassing simple format checks and enabling the server to reach sensitive resources. The vulnerability was fixed in InvenTree versions 1.2.7 and 1.3.0, but it remains a cautionary example for Django apps that perform server-side URL fetching based on user input. From a Django perspective, this class of vulnerability surfaces when developers rely on lightweight format validators and opt-in remote fetch features without implementing robust host controls. Django’s URLValidator ensures only that the string looks like a URL, not that it points to a safe, intended host, and it provides no protection against private or internal destinations. Combined with unrestrained redirects, this pattern enables subtle access to internal networks and services. remediation guidance combines preventing server-side fetches from arbitrary inputs with enforceable host whitelisting, strict request controls, and observable testing. The following example and steps show how to move from a permissive pattern to a secure, defense-in-depth approach that is practical in Django deployments.

Affected Versions

InvenTree 1.2.x before 1.2.7; InvenTree 1.3.x before 1.3.0

Code Fix Example

Django API Security Remediation
Vulnerable:
from django.core.validators import URLValidator
import requests

def fetch_via_url(url):
    # Vulnerable: only validates URL format, then fetches server-side
    URLValidator()(url)
    return requests.get(url, timeout=5, allow_redirects=True)

Fixed:
from urllib.parse import urlparse
import socket
import ipaddress
import requests

def is_private_host(url):
    parsed = urlparse(url)
    host = parsed.hostname
    if not host:
        return True
    try:
        addrs = {addr[4][0] for addr in socket.getaddrinfo(host, None)}
        for a in addrs:
            ip = ipaddress.ip_address(a)
            if ip.is_private or ip.is_loopback:
                return True
        return False
    except Exception:
        return True


def fetch_secure(url):
    if is_private_host(url):
        raise ValueError("Host is internal/private and not allowed")
    return requests.get(url, timeout=5, allow_redirects=False)

CVE References

Choose which optional cookies to allow. You can change this any time.