VYPR
Moderate severityNVD Advisory· Published Sep 29, 2020· Updated Aug 4, 2024

CVE-2020-26137

CVE-2020-26137

Description

urllib3 before 1.25.9 allows CRLF injection if the attacker controls the HTTP request method, as demonstrated by inserting CR and LF control characters in the first argument of putrequest(). NOTE: this is similar to CVE-2020-26116.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

urllib3 before 1.25.9 allows CRLF injection when an attacker controls the HTTP request method, enabling request smuggling.

根因分析

urllib3 的 putrequest() 方法在构造 HTTP 请求时,对 method 参数没有进行充分的清理(sanitization)。攻击者可以在 method 中插入 \r\n(CRLF)控制字符,从而在请求头部注入任意内容。这一漏洞与 Python 标准库 http.client 中的 CVE-2020-26116 类似,因为 urllib3 底层也使用了相同的机制来构建请求行。

攻击场景

要利用此漏洞,攻击者必须能够控制 HTTP 请求的 method 参数。例如,当应用程序将用户输入直接传递给 method 字段(如 conn.request(method=user_input, url="/path")),攻击者可以构造 method="GET / HTTP/1.1\r\nHost: attacker.com\r\nRemainder:" 这样的字符串。这样会在原始请求中添加或修改头部,从而可能绕过安全限制或实现请求走私。

影响与后果

成功利用此漏洞后,攻击者可以执行 HTTP 请求走私(HTTP request smuggling),将恶意请求注入到合法的 HTTP 流中。这可能导致缓存投毒、会话劫持、绕过访问控制等严重后果。由于 urllib3 是 Python 生态中广泛使用的 HTTP 客户端库(被 requests 等库使用),该漏洞影响的软件范围较大。

修复状态

该漏洞在 urllib3 1.25.9 版本中已修复。建议所有使用受影响版本的用户立即升级到 1.25.9 或更高版本。官方公告和补丁信息可在 GitHub 仓库的发布说明中找到[1][2][3]。

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
urllib3PyPI
< 1.25.91.25.9

Affected products

357

Patches

1
1dd69c5c5982

Raise ValueError if method contains control characters (#1800)

https://github.com/urllib3/urllib3Seth Michael LarsonFeb 17, 2020via ghsa
3 files changed · +27 0
  • CHANGES.rst+7 0 modified
    @@ -1,6 +1,13 @@
     Changes
     =======
     
    +master (dev)
    +------------
    +
    +* Raise ``ValueError`` if control characters are given in
    +  the ``method`` parameter of ``HTTPConnection.request()`` (Pull #1800)
    +
    +
     1.25.8 (2020-01-20)
     -------------------
     
    
  • src/urllib3/connection.py+14 0 modified
    @@ -1,4 +1,5 @@
     from __future__ import absolute_import
    +import re
     import datetime
     import logging
     import os
    @@ -58,6 +59,8 @@ class ConnectionError(Exception):
     # (ie test_recent_date is failing) update it to ~6 months before the current date.
     RECENT_DATE = datetime.date(2019, 1, 1)
     
    +_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
    +
     
     class DummyConnection(object):
         """Used to detect a failed ConnectionCls import."""
    @@ -184,6 +187,17 @@ def connect(self):
             conn = self._new_conn()
             self._prepare_conn(conn)
     
    +    def putrequest(self, method, url, *args, **kwargs):
    +        """Send a request to the server"""
    +        match = _CONTAINS_CONTROL_CHAR_RE.search(method)
    +        if match:
    +            raise ValueError(
    +                "Method cannot contain non-token characters %r (found at least %r)"
    +                % (method, match.group())
    +            )
    +
    +        return _HTTPConnection.putrequest(self, method, url, *args, **kwargs)
    +
         def request_chunked(self, method, url, body=None, headers=None):
             """
             Alternative to the common request method, which sends the
    
  • test/with_dummyserver/test_connectionpool.py+6 0 modified
    @@ -677,6 +677,12 @@ def test_dns_error(self):
                 with pytest.raises(MaxRetryError):
                     pool.request("GET", "/test", retries=2)
     
    +    @pytest.mark.parametrize("char", [" ", "\r", "\n", "\x00"])
    +    def test_invalid_method_not_allowed(self, char):
    +        with pytest.raises(ValueError):
    +            with HTTPConnectionPool(self.host, self.port) as pool:
    +                pool.request("GET" + char, "/")
    +
         def test_percent_encode_invalid_target_chars(self):
             with HTTPConnectionPool(self.host, self.port) as pool:
                 r = pool.request("GET", "/echo_params?q=\r&k=\n \n")
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

12

News mentions

0

No linked articles in our index yet.