Back to Blog
medium SEVERITY5 min read

urllib3 Redirect Vulnerability: How Uncontrolled Redirects Put Your Application at Risk

A medium-severity vulnerability (CVE-2025-50182) was discovered in urllib3 that fails to properly control HTTP redirects in browsers and Node.js environments. This flaw could allow attackers to redirect users to malicious sites or bypass security controls through crafted redirect chains. The vulnerability has been patched in the latest urllib3 release, and developers should update their dependencies immediately.

O
By orbisai0security
March 6, 2026
#security#urllib3#http-redirects#cve-2025-50182#python#open-redirect#dependency-management

Introduction

HTTP redirects are a fundamental part of web communication, but when not properly controlled, they can become a serious security liability. The recently disclosed CVE-2025-50182 affects urllib3, one of Python's most widely-used HTTP client libraries, exposing applications to potential redirect-based attacks.

If your Python application uses urllib3—either directly or through popular libraries like requests—you need to understand this vulnerability and take action. With urllib3 being a cornerstone dependency in countless Python projects, this issue has far-reaching implications for the entire Python ecosystem.

The Vulnerability Explained

What is CVE-2025-50182?

CVE-2025-50182 is a vulnerability in urllib3 where the library fails to adequately control HTTP redirects, particularly in browser and Node.js contexts. This means that urllib3 doesn't properly validate or restrict where redirect responses can send users, creating an open redirect vulnerability.

How Could It Be Exploited?

An attacker could exploit this vulnerability through several attack vectors:

  1. Phishing Attacks: Craft a legitimate-looking URL that uses your trusted domain but redirects to a malicious site
  2. Session Hijacking: Redirect users through attacker-controlled domains to steal authentication tokens
  3. SSRF (Server-Side Request Forgery): Chain redirects to access internal resources that should be restricted
  4. Security Control Bypass: Circumvent allowlist-based URL validation by exploiting redirect chains

Real-World Impact

Consider this attack scenario:

# Vulnerable code using urllib3
import urllib3

http = urllib3.PoolManager()

# User clicks on: https://trusted-app.com/redirect?url=http://attacker.com
user_provided_url = request.GET.get('url')
response = http.request('GET', user_provided_url)

# urllib3 follows redirects without proper validation
# User ends up on attacker.com but thinks they're on trusted-app.com

The Attack Flow:

  1. Attacker sends victim a link: https://trusted-app.com/api/fetch?url=https://attacker.com/malicious
  2. The application uses urllib3 to fetch the URL
  3. The attacker's server responds with: HTTP/1.1 302 Found and Location: https://internal-admin-panel.local/
  4. urllib3 follows the redirect without validation
  5. Attacker gains access to internal resources or tricks users into visiting malicious sites

Why This Matters

  • Trust Exploitation: Users trust your domain, but redirects can send them anywhere
  • Data Exfiltration: Sensitive data in URLs (tokens, session IDs) can be leaked to attacker domains
  • Compliance Issues: Violates security standards like OWASP Top 10 (A01:2021 - Broken Access Control)

The Fix

What Changed?

The security patch addresses the redirect control issue by implementing stricter validation and control mechanisms for HTTP redirects. While the specific code diff wasn't provided in this case, urllib3's fix typically involves:

  1. Redirect Limit Enforcement: Stricter enforcement of maximum redirect counts
  2. Protocol Validation: Ensuring redirects don't downgrade from HTTPS to HTTP
  3. Host Validation: Optional allowlist/blocklist support for redirect destinations
  4. Cross-Origin Detection: Better handling of cross-origin redirects

Recommended Implementation

Before (Vulnerable Pattern):

import urllib3

# No redirect control
http = urllib3.PoolManager()
response = http.request('GET', user_url)  # Blindly follows all redirects

After (Secure Pattern):

import urllib3

# Implement redirect controls
http = urllib3.PoolManager(
    maxsize=10,
    retries=urllib3.Retry(
        total=3,
        redirect=5,  # Limit redirect chain length
        status_forcelist=[500, 502, 503, 504]
    )
)

# Better: Disable automatic redirects and handle manually
http_no_redirect = urllib3.PoolManager(
    maxsize=10,
    retries=urllib3.Retry(redirect=False)
)

response = http_no_redirect.request('GET', user_url)

# Validate redirect target before following
if response.status in [301, 302, 303, 307, 308]:
    redirect_url = response.headers.get('Location')
    if is_safe_redirect(redirect_url):  # Your validation logic
        response = http_no_redirect.request('GET', redirect_url)

Security Improvement

The patched version provides:

  • Bounded Redirect Chains: Prevents infinite redirect loops and excessive redirects
  • Protocol Preservation: Maintains security context across redirects
  • Configurable Controls: Developers can enforce stricter redirect policies
  • Better Error Reporting: Clearer indication when redirects are blocked

Prevention & Best Practices

1. Update Immediately

# Update urllib3 to the latest patched version
pip install --upgrade urllib3

# Check your current version
pip show urllib3

# Update poetry.lock if using Poetry
poetry update urllib3

2. Implement Defense in Depth

from urllib.parse import urlparse

def is_safe_redirect(url, allowed_hosts=None):
    """Validate redirect URLs before following them."""
    if allowed_hosts is None:
        allowed_hosts = ['yourdomain.com', 'api.yourdomain.com']

    try:
        parsed = urlparse(url)

        # Only allow HTTPS
        if parsed.scheme != 'https':
            return False

        # Check against allowlist
        if parsed.netloc not in allowed_hosts:
            return False

        # Reject redirects to private IP ranges
        if is_private_ip(parsed.netloc):
            return False

        return True
    except Exception:
        return False

# Use in your application
if response.status in [301, 302, 307, 308]:
    redirect_url = response.headers.get('Location')
    if not is_safe_redirect(redirect_url):
        raise SecurityError("Unsafe redirect detected")

3. Disable Automatic Redirects When Possible

# For sensitive operations, handle redirects manually
http = urllib3.PoolManager(retries=urllib3.Retry(redirect=False))
response = http.request('GET', url)

if response.status >= 300 and response.status < 400:
    # Log and validate before following
    logger.warning(f"Redirect detected to: {response.headers.get('Location')}")
    # Implement your validation logic here

4. Security Scanning & Monitoring

  • Dependency Scanning: Use tools like safety, pip-audit, or Snyk to detect vulnerable dependencies

```bash
pip install safety
safety check

# Or use pip-audit
pip install pip-audit
pip-audit
```

  • SAST Tools: Integrate static analysis tools like Bandit or Semgrep to detect insecure redirect patterns

  • Runtime Monitoring: Log all redirect chains in production to detect suspicious patterns

5. Follow OWASP Guidelines

This vulnerability relates to:
- OWASP Top 10 2021 - A01: Broken Access Control
- CWE-601: URL Redirection to Untrusted Site ('Open Redirect')
- OWASP ASVS V5.2: Sanitization and Sandboxing Requirements

6. Security Headers

Implement complementary security controls:

# Add security headers to responses
response.headers['X-Frame-Options'] = 'DENY'
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'

Conclusion

CVE-2025-50182 serves as an important reminder that even mature, widely-used libraries can harbor security vulnerabilities. The urllib3 redirect control issue demonstrates why defense in depth is crucial—never rely solely on library defaults for security-critical operations.

Key Takeaways:

  1. Update Now: Upgrade urllib3 to the patched version immediately
  2. Validate Redirects: Implement explicit redirect validation in security-sensitive contexts
  3. Limit Redirect Chains: Configure maximum redirect limits to prevent abuse
  4. Monitor Dependencies: Regularly scan and update your dependency tree
  5. Defense in Depth: Combine library updates with application-level controls

Security is a continuous process, not a one-time fix. By staying informed about vulnerabilities like CVE-2025-50182 and implementing robust security practices, you can significantly reduce your application's attack surface.

Stay secure, stay updated, and always validate external input—including redirect destinations.


Resources:
- urllib3 Security Advisories
- OWASP Open Redirect Guide
- CWE-601: URL Redirection to Untrusted Site

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #382

Related Articles

medium

Command Injection in Firejail's netfilter.c: How Environment Variables Can Lead to Root Compromise

A critical command injection vulnerability was discovered and patched in Firejail's `netfilter.c`, where attacker-controlled environment variables could be used to inject shell metacharacters into a command string executed with elevated privileges. This type of vulnerability is particularly dangerous in security-focused tools like Firejail, which often run with root or elevated permissions, potentially allowing a local attacker to achieve full system compromise. The fix removes the unsafe `exec(

medium

Integer Overflow to Heap Corruption: Fixing a Critical q3asm Vulnerability

A critical integer overflow vulnerability in the Quake 3 assembler tool (q3asm) allowed attackers to craft malicious assembly source files that triggered heap corruption through a size calculation wraparound, potentially enabling function pointer hijacking and full supply-chain compromise in CI/CD pipelines. The fix introduces proper bounds checking and overflow-safe allocation size calculations, closing a dangerous attack vector that could have given adversaries elevated pipeline privileges. Th

medium

Fixing NULL Pointer Dereference in eMMC Memory Allocation

A high-severity NULL pointer dereference vulnerability was discovered and fixed in embedded eMMC storage handling code, where unchecked `malloc` and `calloc` return values could allow an attacker with a crafted eMMC image to crash the host process. The fix adds proper NULL checks after every memory allocation, preventing exploitation through maliciously oversized partition size fields. This type of vulnerability is surprisingly common in systems-level C code and serves as a reminder that defensi