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 Orbis AppSec
Published March 6, 2026Reviewed June 3, 2026

Answer Summary

CVE-2025-50182 is an uncontrolled HTTP redirect vulnerability (CWE-601) in Python's urllib3 library that allows attackers to craft malicious redirect chains to redirect users to untrusted sites. The fix involves updating urllib3 to the latest patched version and implementing proper redirect validation that checks redirect targets against an allowlist of trusted domains before following them.

Vulnerability at a Glance

cweCWE-601
fixUpdate urllib3 to the latest patched version and validate redirect destinations
riskUsers can be redirected to malicious sites, enabling phishing or credential theft
languagePython
root causeurllib3 fails to validate redirect target URLs before following them
vulnerabilityUncontrolled HTTP Redirect (Open Redirect)

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

Frequently Asked Questions

What is an uncontrolled HTTP redirect vulnerability?

An uncontrolled HTTP redirect (also called open redirect) occurs when an application follows HTTP redirects without validating that the target URL is trusted, allowing attackers to redirect users to malicious websites.

How do you prevent uncontrolled redirects in Python?

Validate all redirect URLs against an allowlist of trusted domains, limit the number of redirects allowed, and use urllib3's built-in redirect controls or disable automatic redirects when handling sensitive operations.

What CWE is uncontrolled HTTP redirect?

Uncontrolled HTTP redirects are classified as CWE-601: URL Redirection to Untrusted Site ('Open Redirect').

Is limiting redirect count enough to prevent this vulnerability?

No, limiting redirect count alone is insufficient. Attackers can still redirect to malicious sites within the allowed count. You must validate that each redirect target is a trusted domain.

Can static analysis detect uncontrolled redirect vulnerabilities?

Yes, static analysis tools like Semgrep, Bandit, and commercial SAST solutions can detect patterns where redirect URLs are followed without proper validation, though runtime testing is also recommended.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #382

Related Articles

high

How missing Dependabot cooldown happens in GitHub Actions and how to fix it

A high-severity configuration vulnerability was discovered in a `.github/dependabot.yml` file that lacked a cooldown period for package updates. Without this safeguard, Dependabot could immediately propose updates to newly published package versions—including potentially malicious or unstable releases. The fix adds a simple `cooldown` block with a 7-day waiting period before any new package version is suggested.

high

How Server-Sent Events Injection via Unsanitized Newlines happens in Node.js h3 and how to fix it

A high-severity Server-Sent Events (SSE) injection vulnerability (CVE-2026-33128) was discovered in the h3 HTTP framework, where unsanitized newline characters in event stream fields could allow attackers to inject arbitrary SSE messages. The fix upgrades h3 from version 1.15.5 to 1.15.6 in the frontend's dependency tree, ensuring that newline characters are properly sanitized before being written to event streams.

high

How Memory Exhaustion via Large Comma-Separated Selector Lists happens in Python Soup Sieve and how to fix it

A high-severity memory exhaustion vulnerability (CVE-2026-49476) was discovered in Soup Sieve version 2.8.3, affecting Python applications that parse CSS selectors from user-controlled input. The vulnerability allows attackers to craft malicious selector lists that consume excessive memory, potentially causing denial of service. The fix involves upgrading to soupsieve 2.8.4, which implements proper resource limits on selector parsing.

high

How prototype pollution via `__proto__` key happens in Node.js defu and how to fix it

A high-severity prototype pollution vulnerability (CVE-2026-35209) was discovered in the `defu` package version 6.1.4, which allowed attackers to inject properties into JavaScript's `Object.prototype` via the `__proto__` key in defaults arguments. The fix upgrades `defu` to version 6.1.5 in the frontend's dependency tree, protecting downstream consumers like `c12` and `dotenv` configuration loaders from malicious property injection.

critical

How buffer overflow in memcpy() happens in Node.js N-API bindings and how to fix it

A critical buffer overflow vulnerability was discovered in the GetBufferAsVector() function in examples_nodejs/src/zupt_napi.cpp, where memcpy() copied data from JavaScript Uint8Array buffers without proper bounds validation. This vulnerability could allow attackers to trigger memory corruption by providing maliciously crafted input arrays to the native Node.js module, potentially leading to crashes or arbitrary code execution.

high

How memory exhaustion via large comma-separated selector lists happens in Python soupsieve and how to fix it

A high-severity memory exhaustion vulnerability (CVE-2026-49476) was discovered in soupsieve 2.8.3, a CSS selector library used by BeautifulSoup in Python. An attacker who could influence CSS selector input could craft large comma-separated selector lists to exhaust system memory, causing denial of service. The fix upgrades soupsieve from 2.8.3 to 2.8.4 in the backend's `uv.lock` dependency file.