158 lines
6.6 KiB
Diff
158 lines
6.6 KiB
Diff
From 01220354d389cd05474713f8c982d05c9b17aafb Mon Sep 17 00:00:00 2001
|
|
From: Seth Michael Larson <sethmichaellarson@gmail.com>
|
|
Date: Mon, 2 Oct 2023 11:43:46 -0500
|
|
Subject: [PATCH] Backport GHSA-v845-jxx5-vc9f (#3139)
|
|
|
|
Co-authored-by: Quentin Pradet <quentin.pradet@gmail.com>
|
|
Co-authored-by: Illia Volochii <illia.volochii@gmail.com>
|
|
|
|
Conflict:NA
|
|
Reference:https://github.com/urllib3/urllib3/commit/01220354d389cd05474713f8c982d05c9b17aafb
|
|
|
|
---
|
|
src/urllib3/util/retry.py | 2 +-
|
|
test/test_retry.py | 4 ++--
|
|
test/test_retry_deprecated.py | 2 +-
|
|
test/with_dummyserver/test_poolmanager.py | 24 ++++++++++++++++++-----
|
|
4 files changed, 28 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/src/urllib3/util/retry.py b/src/urllib3/util/retry.py
|
|
index 2490d5e5b6..60ef6c4f3f 100644
|
|
--- a/src/urllib3/util/retry.py
|
|
+++ b/src/urllib3/util/retry.py
|
|
@@ -235,7 +235,7 @@ class Retry(object):
|
|
RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503])
|
|
|
|
#: Default headers to be used for ``remove_headers_on_redirect``
|
|
- DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Authorization"])
|
|
+ DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Cookie", "Authorization"])
|
|
|
|
#: Maximum backoff time.
|
|
DEFAULT_BACKOFF_MAX = 120
|
|
diff --git a/test/test_retry.py b/test/test_retry.py
|
|
index 21ba1e92e1..95a33e7461 100644
|
|
--- a/test/test_retry.py
|
|
+++ b/test/test_retry.py
|
|
@@ -293,12 +293,12 @@ def test_retry_method_not_in_whitelist(self):
|
|
def test_retry_default_remove_headers_on_redirect(self):
|
|
retry = Retry()
|
|
|
|
- assert list(retry.remove_headers_on_redirect) == ["authorization"]
|
|
+ assert retry.remove_headers_on_redirect == {"authorization", "cookie"}
|
|
|
|
def test_retry_set_remove_headers_on_redirect(self):
|
|
retry = Retry(remove_headers_on_redirect=["X-API-Secret"])
|
|
|
|
- assert list(retry.remove_headers_on_redirect) == ["x-api-secret"]
|
|
+ assert retry.remove_headers_on_redirect == {"x-api-secret"}
|
|
|
|
@pytest.mark.parametrize("value", ["-1", "+1", "1.0", six.u("\xb2")]) # \xb2 = ^2
|
|
def test_parse_retry_after_invalid(self, value):
|
|
diff --git a/test/test_retry_deprecated.py b/test/test_retry_deprecated.py
|
|
index f55c5d846b..5133a51afa 100644
|
|
--- a/test/test_retry_deprecated.py
|
|
+++ b/test/test_retry_deprecated.py
|
|
@@ -295,7 +295,7 @@ def test_retry_method_not_in_whitelist(self):
|
|
def test_retry_default_remove_headers_on_redirect(self):
|
|
retry = Retry()
|
|
|
|
- assert list(retry.remove_headers_on_redirect) == ["authorization"]
|
|
+ assert retry.remove_headers_on_redirect == {"authorization", "cookie"}
|
|
|
|
def test_retry_set_remove_headers_on_redirect(self):
|
|
retry = Retry(remove_headers_on_redirect=["X-API-Secret"])
|
|
diff --git a/test/with_dummyserver/test_poolmanager.py b/test/with_dummyserver/test_poolmanager.py
|
|
index fa07a372a9..02a38115c5 100644
|
|
--- a/test/with_dummyserver/test_poolmanager.py
|
|
+++ b/test/with_dummyserver/test_poolmanager.py
|
|
@@ -141,7 +141,7 @@ def test_redirect_cross_host_remove_headers(self):
|
|
"GET",
|
|
"%s/redirect" % self.base_url,
|
|
fields={"target": "%s/headers" % self.base_url_alt},
|
|
- headers={"Authorization": "foo"},
|
|
+ headers={"Authorization": "foo", "Cookie": "foo=bar"},
|
|
)
|
|
|
|
assert r.status == 200
|
|
@@ -149,12 +149,13 @@ def test_redirect_cross_host_remove_headers(self):
|
|
data = json.loads(r.data.decode("utf-8"))
|
|
|
|
assert "Authorization" not in data
|
|
+ assert "Cookie" not in data
|
|
|
|
r = http.request(
|
|
"GET",
|
|
"%s/redirect" % self.base_url,
|
|
fields={"target": "%s/headers" % self.base_url_alt},
|
|
- headers={"authorization": "foo"},
|
|
+ headers={"authorization": "foo", "cookie": "foo=bar"},
|
|
)
|
|
|
|
assert r.status == 200
|
|
@@ -163,6 +164,8 @@ def test_redirect_cross_host_remove_headers(self):
|
|
|
|
assert "authorization" not in data
|
|
assert "Authorization" not in data
|
|
+ assert "cookie" not in data
|
|
+ assert "Cookie" not in data
|
|
|
|
def test_redirect_cross_host_no_remove_headers(self):
|
|
with PoolManager() as http:
|
|
@@ -170,7 +173,7 @@ def test_redirect_cross_host_no_remove_headers(self):
|
|
"GET",
|
|
"%s/redirect" % self.base_url,
|
|
fields={"target": "%s/headers" % self.base_url_alt},
|
|
- headers={"Authorization": "foo"},
|
|
+ headers={"Authorization": "foo", "Cookie": "foo=bar"},
|
|
retries=Retry(remove_headers_on_redirect=[]),
|
|
)
|
|
|
|
@@ -179,6 +182,7 @@ def test_redirect_cross_host_no_remove_headers(self):
|
|
data = json.loads(r.data.decode("utf-8"))
|
|
|
|
assert data["Authorization"] == "foo"
|
|
+ assert data["Cookie"] == "foo=bar"
|
|
|
|
def test_redirect_cross_host_set_removed_headers(self):
|
|
with PoolManager() as http:
|
|
@@ -186,7 +190,11 @@ def test_redirect_cross_host_set_removed_headers(self):
|
|
"GET",
|
|
"%s/redirect" % self.base_url,
|
|
fields={"target": "%s/headers" % self.base_url_alt},
|
|
- headers={"X-API-Secret": "foo", "Authorization": "bar"},
|
|
+ headers={
|
|
+ "X-API-Secret": "foo",
|
|
+ "Authorization": "bar",
|
|
+ "Cookie": "foo=bar",
|
|
+ },
|
|
retries=Retry(remove_headers_on_redirect=["X-API-Secret"]),
|
|
)
|
|
|
|
@@ -196,12 +204,17 @@ def test_redirect_cross_host_set_removed_headers(self):
|
|
|
|
assert "X-API-Secret" not in data
|
|
assert data["Authorization"] == "bar"
|
|
+ assert data["Cookie"] == "foo=bar"
|
|
|
|
r = http.request(
|
|
"GET",
|
|
"%s/redirect" % self.base_url,
|
|
fields={"target": "%s/headers" % self.base_url_alt},
|
|
- headers={"x-api-secret": "foo", "authorization": "bar"},
|
|
+ headers={
|
|
+ "x-api-secret": "foo",
|
|
+ "authorization": "bar",
|
|
+ "cookie": "foo=bar",
|
|
+ },
|
|
retries=Retry(remove_headers_on_redirect=["X-API-Secret"]),
|
|
)
|
|
|
|
@@ -212,6 +225,7 @@ def test_redirect_cross_host_set_removed_headers(self):
|
|
assert "x-api-secret" not in data
|
|
assert "X-API-Secret" not in data
|
|
assert data["Authorization"] == "bar"
|
|
+ assert data["Cookie"] == "foo=bar"
|
|
|
|
def test_redirect_without_preload_releases_connection(self):
|
|
with PoolManager(block=True, maxsize=2) as http:
|