Skip to content

Commit 708eaa1

Browse files
Compare the origin, not the host, and add a NEWS entry
The origin includes the scheme, so credentials are no longer sent if the connection is downgraded from HTTPS to HTTP.
1 parent 64879ff commit 708eaa1

3 files changed

Lines changed: 39 additions & 22 deletions

File tree

Lib/test/test_urllib2.py

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,9 +1429,7 @@ def request(conn, method, url, *pos, **kw):
14291429
fp = urllib.request.urlopen("http://python.org/path")
14301430
self.assertEqual(fp.geturl(), "http://python.org/path?query")
14311431

1432-
def test_redirect_to_cross_domain_with_sensitive_header(self):
1433-
from_url = "http://example.com/index.html"
1434-
to_url = "http://cracker.com/index.html"
1432+
def redirect_with_sensitive_headers(self, from_url, to_url):
14351433
h = urllib.request.HTTPRedirectHandler()
14361434
o = h.parent = MockOpener()
14371435
req = Request(from_url)
@@ -1440,24 +1438,36 @@ def test_redirect_to_cross_domain_with_sensitive_header(self):
14401438
req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
14411439
h.http_error_302(req, MockFile(), 302, "",
14421440
MockHeaders({"location": to_url}))
1443-
1444-
self.assertNotIn("Authorization", o.req.headers)
1445-
self.assertNotIn("Cookie", o.req.headers)
1446-
1447-
def test_redirect_to_same_domain_with_sensitive_header(self):
1448-
from_url = "http://example.com/index.html"
1449-
to_url = "http://example.com/index.html"
1450-
h = urllib.request.HTTPRedirectHandler()
1451-
o = h.parent = MockOpener()
1452-
req = Request(from_url)
1453-
req.add_header("Authorization", "Basic foo")
1454-
req.add_header("Cookie", "bar")
1455-
req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
1456-
h.http_error_302(req, MockFile(), 302, "",
1457-
MockHeaders({"location": to_url}))
1458-
1459-
self.assertIn("Authorization", o.req.headers)
1460-
self.assertIn("Cookie", o.req.headers)
1441+
return o.req.headers
1442+
1443+
def test_redirect_to_same_origin_with_sensitive_header(self):
1444+
for to_url in [
1445+
"http://example.com/index.html",
1446+
"http://example.com/other.html",
1447+
]:
1448+
with self.subTest(to_url):
1449+
headers = self.redirect_with_sensitive_headers(
1450+
"http://example.com/index.html", to_url)
1451+
self.assertIn("Authorization", headers)
1452+
self.assertIn("Cookie", headers)
1453+
1454+
def test_redirect_to_other_origin_with_sensitive_header(self):
1455+
# The origin includes the scheme, the host and the port, so
1456+
# credentials are not sent if any of them differs (gh-77842).
1457+
for from_url, to_url in [
1458+
# other host
1459+
("http://example.com/index.html", "http://cracker.com/index.html"),
1460+
# other port
1461+
("http://example.com/index.html", "http://example.com:8080/i.html"),
1462+
# downgrade from HTTPS to HTTP
1463+
("https://example.com/index.html", "http://example.com/index.html"),
1464+
# upgrade from HTTP to HTTPS
1465+
("http://example.com/index.html", "https://example.com/index.html"),
1466+
]:
1467+
with self.subTest(from_url=from_url, to_url=to_url):
1468+
headers = self.redirect_with_sensitive_headers(from_url, to_url)
1469+
self.assertNotIn("Authorization", headers)
1470+
self.assertNotIn("Cookie", headers)
14611471

14621472
def test_redirect_encoding(self):
14631473
# Some characters in the redirect target may need special handling,

Lib/urllib/request.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,11 @@ def redirect_request(self, req, fp, code, msg, headers, newurl):
655655
origin_req_host=req.origin_req_host,
656656
unverifiable=True)
657657

658+
# Do not send credentials to other origin. The origin includes
659+
# the scheme, so they are not sent if the connection is downgraded
660+
# from HTTPS to HTTP either.
658661
SENSITIVE_HEADERS = ("authorization", "cookie")
659-
if newrequest.host != req.host:
662+
if (newrequest.type, newrequest.host) != (req.type, req.host):
660663
newrequest.headers = {k: v for k, v in newrequest.headers.items()
661664
if k.lower() not in SENSITIVE_HEADERS}
662665

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:class:`urllib.request.HTTPRedirectHandler` no longer sends the
2+
``Authorization`` and ``Cookie`` headers when it is redirected to other
3+
origin. The origin includes the scheme, so they are no longer sent if the
4+
connection is downgraded from HTTPS to HTTP either.

0 commit comments

Comments
 (0)