File urllib3-cve-2020-26137.patch of Package python-urllib3
From d126a7654af03df4ec26ab1be4614279d6c1fec5 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <sethmichaellarson@gmail.com>
Date: Wed, 12 Feb 2020 20:03:54 -0600
Subject: [PATCH 1/4] Raise ValueError if method contains control characters
---
urllib3/connection.py | 13 +++++++++++++
test/with_dummyserver/test_connectionpool.py | 6 ++++++
test/with_dummyserver/test_poolmanager.py | 6 ++++++
3 files changed, 25 insertions(+)
diff --git a/src/urllib3/connection.py b/src/urllib3/connection.py
index 71e6790b1..c315078b4 100644
--- a/urllib3/connection.py
+++ b/urllib3/connection.py
@@ -1,4 +1,5 @@
from __future__ import absolute_import
+import re
import datetime
import logging
import os
@@ -60,6 +61,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("[\x00-\x20\x7f]")
+
class DummyConnection(object):
"""Used to detect a failed ConnectionCls import."""
@@ -194,6 +197,16 @@ def connect(self):
conn = self._new_conn()
self._prepare_conn(conn)
+ def putrequest(self, method, url, *args, **kwargs):
+ match = _CONTAINS_CONTROL_CHAR_RE.search(method)
+ if match:
+ raise ValueError(
+ "Method cannot contain control 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
diff --git a/test/with_dummyserver/test_connectionpool.py b/test/with_dummyserver/test_connectionpool.py
index 57f0dbd2f..79cbd2718 100644
--- a/test/with_dummyserver/test_connectionpool.py
+++ b/test/with_dummyserver/test_connectionpool.py
@@ -657,6 +657,11 @@ def test_dns_error(self):
pool = HTTPConnectionPool('thishostdoesnotexist.invalid', self.port, timeout=0.001)
self.assertRaises(MaxRetryError, pool.request, 'GET', '/test', retries=2)
+ def test_invalid_method_not_allowed(self):
+ for char in [" ", "\r", "\n", "\x00"]:
+ pool = HTTPConnectionPool(self.host, self.port)
+ self.assertRaises(ValueError, pool.request, 'GET' + char, '/')
+
def test_source_address(self):
for addr, is_ipv6 in VALID_SOURCE_ADDRESSES:
if is_ipv6 and not HAS_IPV6_AND_DNS:
From 842d80008087045257cbf5df7e12c23d104159c4 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <sethmichaellarson@gmail.com>
Date: Thu, 13 Feb 2020 14:14:11 -0600
Subject: [PATCH 3/4] Restrict all non-tokens
---
src/urllib3/connection.py | 4 ++--
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/urllib3/connection.py b/urllib3/connection.py
index c315078b4..019f6e437 100644
--- a/urllib3/connection.py
+++ b/urllib3/connection.py
@@ -61,7 +61,7 @@ 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("[\x00-\x20\x7f]")
+_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
class DummyConnection(object):
@@ -201,7 +201,7 @@ def putrequest(self, method, url, *args, **kwargs):
match = _CONTAINS_CONTROL_CHAR_RE.search(method)
if match:
raise ValueError(
- "Method cannot contain control characters. %r (found at least %r)"
+ "Method cannot contain non-token characters %r (found at least %r)"
% (method, match.group())
)
From 695f832bb1aec4c5453530b6c25e57a3bb0c05a9 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <sethmichaellarson@gmail.com>
Date: Sun, 16 Feb 2020 21:31:40 -0600
Subject: [PATCH 4/4] Add a simple docstring to putrequest()
---
src/urllib3/connection.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/urllib3/connection.py b/urllib3/connection.py
index 019f6e437..f7b176093 100644
--- a/urllib3/connection.py
+++ b/urllib3/connection.py
@@ -198,6 +198,7 @@ def connect(self):
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(