diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-05-22 10:41:30 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-22 10:41:30 (GMT) |
commit | 3d5dd1eee265ec43dd96d89656c2a1c207dd5815 (patch) | |
tree | 2ec0584c1df5acf29810bfd0b51950be31d09ddf | |
parent | b53d0ff4312cc2a67b9c5752844b140c08514648 (diff) | |
download | cpython-3d5dd1eee265ec43dd96d89656c2a1c207dd5815.zip cpython-3d5dd1eee265ec43dd96d89656c2a1c207dd5815.tar.gz cpython-3d5dd1eee265ec43dd96d89656c2a1c207dd5815.tar.bz2 |
[3.9] gh-99889: Fix directory traversal security flaw in uu.decode() (GH-104096) (#104331)
(cherry picked from commit 0aeda297931820436a50b78f4f7f0597274b5df4)
Co-authored-by: Sam Carroll <70000253+samcarroll42@users.noreply.github.com>
-rw-r--r-- | Lib/test/test_uu.py | 28 | ||||
-rw-r--r--[-rwxr-xr-x] | Lib/uu.py | 9 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Security/2023-05-02-17-56-32.gh-issue-99889.l664SU.rst | 2 |
3 files changed, 38 insertions, 1 deletions
diff --git a/Lib/test/test_uu.py b/Lib/test/test_uu.py index 4c639b7..410eb8e 100644 --- a/Lib/test/test_uu.py +++ b/Lib/test/test_uu.py @@ -145,6 +145,34 @@ class UUTest(unittest.TestCase): uu.encode(inp, out, filename) self.assertIn(safefilename, out.getvalue()) + def test_no_directory_traversal(self): + relative_bad = b"""\ +begin 644 ../../../../../../../../tmp/test1 +$86)C"@`` +` +end +""" + with self.assertRaisesRegex(uu.Error, 'directory'): + uu.decode(io.BytesIO(relative_bad)) + if os.altsep: + relative_bad_bs = relative_bad.replace(b'/', b'\\') + with self.assertRaisesRegex(uu.Error, 'directory'): + uu.decode(io.BytesIO(relative_bad_bs)) + + absolute_bad = b"""\ +begin 644 /tmp/test2 +$86)C"@`` +` +end +""" + with self.assertRaisesRegex(uu.Error, 'directory'): + uu.decode(io.BytesIO(absolute_bad)) + if os.altsep: + absolute_bad_bs = absolute_bad.replace(b'/', b'\\') + with self.assertRaisesRegex(uu.Error, 'directory'): + uu.decode(io.BytesIO(absolute_bad_bs)) + + class UUStdIOTest(unittest.TestCase): def setUp(self): diff --git a/Lib/uu.py b/Lib/uu.py index 9f1f37f..9fe252a 100755..100644 --- a/Lib/uu.py +++ b/Lib/uu.py @@ -130,7 +130,14 @@ def decode(in_file, out_file=None, mode=None, quiet=False): # If the filename isn't ASCII, what's up with that?!? out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii") if os.path.exists(out_file): - raise Error('Cannot overwrite existing file: %s' % out_file) + raise Error(f'Cannot overwrite existing file: {out_file}') + if (out_file.startswith(os.sep) or + f'..{os.sep}' in out_file or ( + os.altsep and + (out_file.startswith(os.altsep) or + f'..{os.altsep}' in out_file)) + ): + raise Error(f'Refusing to write to {out_file} due to directory traversal') if mode is None: mode = int(hdrfields[1], 8) # diff --git a/Misc/NEWS.d/next/Security/2023-05-02-17-56-32.gh-issue-99889.l664SU.rst b/Misc/NEWS.d/next/Security/2023-05-02-17-56-32.gh-issue-99889.l664SU.rst new file mode 100644 index 0000000..b7002e8 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2023-05-02-17-56-32.gh-issue-99889.l664SU.rst @@ -0,0 +1,2 @@ +Fixed a security in flaw in :func:`uu.decode` that could allow for +directory traversal based on the input if no ``out_file`` was specified. |