Skip to content

Commit 28b0ed3

Browse files
authored
Merge pull request #14 from ActiveState/cve-2022-0391
Address CVE-2022-0391 for urlparse
2 parents 75f0a73 + 2bff6bd commit 28b0ed3

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

Lib/test/test_urlparse.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Copyright (C) 2022 ActiveState Software Inc.
2+
# test_urlparse.py is licensed under the PSFLv2 License.
3+
# See the file LICENSE for details.
4+
15
from test import test_support
26
import sys
37
import unicodedata
@@ -569,6 +573,36 @@ def test_telurl_params(self):
569573
self.assertEqual(p1.params, 'phone-context=+1-914-555')
570574

571575

576+
def test_urlsplit_remove_unsafe_bytes(self):
577+
# Remove ASCII tabs and newlines from input
578+
url = "http://www.python.org/java\nscript:\talert('msg\r\n')/#frag"
579+
p = urlparse.urlsplit(url)
580+
self.assertEqual(p.scheme, "http")
581+
self.assertEqual(p.netloc, "www.python.org")
582+
self.assertEqual(p.path, "/javascript:alert('msg')/")
583+
self.assertEqual(p.query, "")
584+
self.assertEqual(p.fragment, "frag")
585+
self.assertEqual(p.username, None)
586+
self.assertEqual(p.password, None)
587+
self.assertEqual(p.hostname, "www.python.org")
588+
self.assertEqual(p.port, None)
589+
self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/#frag")
590+
591+
# Remove ASCII tabs and newlines from input as unicode.
592+
url = u"http://www.python.org/java\nscript:\talert('msg\r\n')/#frag"
593+
p = urlparse.urlsplit(url)
594+
self.assertEqual(p.scheme, u"http")
595+
self.assertEqual(p.netloc, u"www.python.org")
596+
self.assertEqual(p.path, u"/javascript:alert('msg')/")
597+
self.assertEqual(p.query, u"")
598+
self.assertEqual(p.fragment, u"frag")
599+
self.assertEqual(p.username, None)
600+
self.assertEqual(p.password, None)
601+
self.assertEqual(p.hostname, u"www.python.org")
602+
self.assertEqual(p.port, None)
603+
self.assertEqual(p.geturl(), u"http://www.python.org/javascript:alert('msg')/#frag")
604+
605+
572606
def test_attributes_bad_port(self):
573607
"""Check handling of non-integer ports."""
574608
p = urlparse.urlsplit("http://www.example.net:foo")

Lib/urlparse.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Copyright (C) 2022 ActiveState Software Inc.
2+
# urlparse.py is licensed under the PSFLv2 License.
3+
# See the file LICENSE for details.
4+
15
"""Parse (absolute and relative) URLs.
26
37
urlparse module is based upon the following RFC specifications.
@@ -62,6 +66,9 @@
6266
'0123456789'
6367
'+-.')
6468

69+
# Unsafe bytes to be removed per WHATWG spec
70+
_UNSAFE_URL_BYTES_TO_REMOVE = ['\t', '\r', '\n']
71+
6572
MAX_CACHE_SIZE = 20
6673
_parse_cache = {}
6774

@@ -203,6 +210,8 @@ def urlsplit(url, scheme='', allow_fragments=True):
203210
if url[:i] == 'http': # optimize the common case
204211
scheme = url[:i].lower()
205212
url = url[i+1:]
213+
for b in _UNSAFE_URL_BYTES_TO_REMOVE:
214+
url = url.replace(b, '')
206215
if url[:2] == '//':
207216
netloc, url = _splitnetloc(url, 2)
208217
if (('[' in netloc and ']' not in netloc) or
@@ -227,6 +236,9 @@ def urlsplit(url, scheme='', allow_fragments=True):
227236
# not a port number
228237
scheme, url = url[:i].lower(), rest
229238

239+
for b in _UNSAFE_URL_BYTES_TO_REMOVE:
240+
url = url.replace(b, '')
241+
230242
if url[:2] == '//':
231243
netloc, url = _splitnetloc(url, 2)
232244
if (('[' in netloc and ']' not in netloc) or

Misc/NEWS.d/2.7.18.5.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.. bpo: 0
2+
.. date: 2022-06-27
3+
.. nonce: caft@D
4+
.. release date: 2022-06-27
5+
.. section: Library
6+
7+
Address CVE-2022-0391 in urlparse

0 commit comments

Comments
 (0)