CVE-2025-0938 Overview
CVE-2025-0938 is an Improper Input Validation vulnerability in the Python standard library's URL parsing functions. The urllib.parse.urlsplit and urllib.parse.urlparse functions incorrectly accept domain names containing square brackets, which violates RFC 3986 specifications. According to RFC 3986, square brackets are reserved delimiters meant exclusively for specifying IPv6 and IPvFuture hosts in URLs. This non-compliant behavior can lead to differential parsing between Python's URL parser and other specification-compliant parsers, potentially enabling security bypasses.
Critical Impact
Applications relying on Python's URL parsing for security decisions may be vulnerable to URL-based attacks due to parsing inconsistencies with other security components.
Affected Products
- Python Standard Library (urllib.parse module)
- Applications using urllib.parse.urlsplit() function
- Applications using urllib.parse.urlparse() function
Discovery Timeline
- 2025-01-31 - CVE-2025-0938 published to NVD
- 2025-11-03 - Last updated in NVD database
Technical Details for CVE-2025-0938
Vulnerability Analysis
The vulnerability exists in Python's urllib.parse module, specifically in the urlsplit and urlparse functions. These functions are fundamental to URL handling in Python applications and are widely used for parsing and validating URLs before processing them further.
The core issue is that Python's URL parser accepts domain names with square brackets embedded in them, even when those brackets are not being used to delimit IPv6 or IPvFuture addresses. This behavior contradicts RFC 3986, which strictly reserves square brackets ([ and ]) as delimiters for IP-literal hosts.
When different URL parsers interpret the same URL differently, it creates a parsing differential. An attacker can craft a malicious URL that Python interprets one way while another security component (such as a web application firewall, proxy, or backend server) interprets it differently. This inconsistency can be exploited to bypass security controls, access unauthorized resources, or conduct SSRF attacks.
Root Cause
The root cause is classified as CWE-20 (Improper Input Validation). The urllib.parse module fails to properly validate that square brackets in the host portion of a URL are only used in the context of IPv6 or IPvFuture address literals. Instead of rejecting malformed domain names containing square brackets, the parser accepts them, creating non-RFC-compliant behavior.
Attack Vector
This vulnerability is exploitable over the network. An attacker can supply a specially crafted URL containing square brackets in the domain name to a Python application. If the application uses urllib.parse.urlsplit() or urllib.parse.urlparse() to extract the hostname and then passes this information to other components that parse URLs according to RFC 3986, the differential parsing can lead to:
- Security bypass scenarios where access controls are circumvented
- Server-Side Request Forgery (SSRF) attacks where the target host differs from what was validated
- Open redirect vulnerabilities when URL validation is bypassed
- Request routing manipulation in microservice architectures
The attack requires network access and specific conditions to be exploitable, as the attacker must find a scenario where differential parsing impacts security decisions.
Detection Methods for CVE-2025-0938
Indicators of Compromise
- URLs containing square brackets in the domain name portion (outside of IPv6 literal context)
- Unusual URL patterns in application logs with characters like [ or ] in hostnames
- Failed requests or unexpected routing behavior in systems downstream from Python URL parsing
Detection Strategies
- Audit application code for uses of urllib.parse.urlsplit() and urllib.parse.urlparse() where the parsed hostname is used for security decisions
- Monitor web application logs for URLs with malformed domain names containing square brackets
- Implement input validation at the application layer to reject URLs with non-RFC-compliant hostnames before parsing
Monitoring Recommendations
- Review web server access logs for requests containing square brackets in unexpected URL positions
- Set up alerts for URL parsing errors or discrepancies between different parsing layers in your infrastructure
- Monitor for SSRF-related indicators if your application makes outbound requests based on user-supplied URLs
How to Mitigate CVE-2025-0938
Immediate Actions Required
- Identify all Python applications in your environment that use urllib.parse.urlsplit() or urllib.parse.urlparse()
- Prioritize patching applications that use parsed URLs for security decisions, SSRF prevention, or access control
- Implement additional URL validation to reject domains containing square brackets outside of IPv6 literal context
- Review and update Python installations to patched versions when available
Patch Information
The Python development team has released patches addressing this vulnerability across multiple Python branches. The fixes ensure that square brackets in domain names are properly validated according to RFC 3986.
Relevant patch commits are available:
For complete details, refer to the Python Security Announcement, Debian LTS Security Advisory, and NetApp Security Advisory.
Workarounds
- Implement custom URL validation that rejects hostnames containing square brackets unless they match the IPv6 literal pattern [IPv6address]
- Use additional URL parsing libraries that are RFC 3986 compliant as a secondary validation step
- Apply web application firewall rules to block requests with malformed URLs containing unexpected square brackets in domain names
- Consider wrapping urllib.parse functions with custom validation logic until patches can be applied
# Workaround: Custom URL validation wrapper
import urllib.parse
import re
def validate_and_parse_url(url):
"""Parse URL with additional validation for RFC 3986 compliance."""
parsed = urllib.parse.urlsplit(url)
# Check for square brackets outside IPv6 literal context
if parsed.hostname and '[' in parsed.hostname:
# Only allow if it matches IPv6 literal pattern
if not re.match(r'^\[[\da-fA-F:]+\]$', parsed.hostname):
raise ValueError("Invalid hostname: square brackets not permitted outside IPv6 literals")
return parsed
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

