diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index c292d74f84a93c..074ab563f1c8a6 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -426,6 +426,22 @@ def test_ftp_nonexisting(self): self.assertFalse(e.exception.filename) self.assertTrue(e.exception.reason) + def test_ftp_illegalhost(self): + illegal_ftp_hosts = [ + 'ftp://foo:bar%0d%0aINJECTED@example.net/file.png', + 'fTp://foo:bar%0d%0aINJECTED@example.net/file.png', + 'FTP://foo:bar%0d%0aINJECTED@example.net/file.png', + 'ftp://foo:bar%0aINJECTED@example.net/file.png', + 'fTp://foo:bar%0aINJECTED@example.net/file.png', + 'FTP://foo:bar%0aINJECTED@example.net/file.png' + ] + + for host in illegal_ftp_hosts: + with self.assertRaises(urllib.error.URLError) as e: + urlopen(host) + self.assertFalse(e.exception.filename) + self.assertTrue(e.exception.reason) + @patch.object(urllib.request, 'MAXFTPCACHE', 0) def test_ftp_cache_pruning(self): self.fakeftp() diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index a192d527d8bc9a..816b1e2685044f 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1502,6 +1502,9 @@ def ftp_open(self, req): host = req.host if not host: raise URLError('ftp error: no host given') + target_host = unquote(host) + if '\n' in target_host: + raise URLError("illegal ftp host") host, port = splitport(host) if port is None: port = ftplib.FTP_PORT diff --git a/Misc/NEWS b/Misc/NEWS index bdfe53be957c22..33ab8970e0e91a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -365,6 +365,9 @@ Extension Modules Library ------- +- bpo-29606: urllib throwing an URL exception on any URLs that + contain one of '\n' for the FTP protocol. Patch by Dong-hee Na + - [Security] bpo-29591: Update expat copy from 2.1.1 to 2.2.0 to get fixes of CVE-2016-0718 and CVE-2016-4472. See https://sourceforge.net/p/expat/bugs/537/ for more information.