diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-05-09 16:46:47 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-09 16:46:47 (GMT) |
commit | cfa4295cd14ce00fe5263c7083aa5a73b515828d (patch) | |
tree | 3e523422b308b3d5861fda929ac4900ccdc594aa | |
parent | d77e77c363a170f4435cbe826628b6a347654d9e (diff) | |
download | cpython-cfa4295cd14ce00fe5263c7083aa5a73b515828d.zip cpython-cfa4295cd14ce00fe5263c7083aa5a73b515828d.tar.gz cpython-cfa4295cd14ce00fe5263c7083aa5a73b515828d.tar.bz2 |
[3.10] gh-99889: Fix directory traversal security flaw in uu.decode() (GH-104096) (#104330)
gh-99889: Fix directory traversal security flaw in uu.decode() (GH-104096)
* Fix directory traversal security flaw in uu.decode()
* also check absolute paths and os.altsep
* Add a regression test.
---------
(cherry picked from commit 0aeda297931820436a50b78f4f7f0597274b5df4)
[Google]
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 753b31e..8cc1c07 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. |