mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-99889: Fix directory traversal security flaw in uu.decode() (#104096)
* Fix directory traversal security flaw in uu.decode() * also check absolute paths and os.altsep * Add a regression test. --------- Co-authored-by: Gregory P. Smith <greg@krypto.org> [Google]
This commit is contained in:
parent
afe7703744
commit
0aeda29793
3 changed files with 38 additions and 1 deletions
|
@ -147,6 +147,34 @@ class UUTest(unittest.TestCase):
|
||||||
uu.encode(inp, out, filename)
|
uu.encode(inp, out, filename)
|
||||||
self.assertIn(safefilename, out.getvalue())
|
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):
|
class UUStdIOTest(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
9
Lib/uu.py
Executable file → Normal file
9
Lib/uu.py
Executable file → Normal file
|
@ -133,7 +133,14 @@ def decode(in_file, out_file=None, mode=None, quiet=False):
|
||||||
# If the filename isn't ASCII, what's up with that?!?
|
# If the filename isn't ASCII, what's up with that?!?
|
||||||
out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii")
|
out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii")
|
||||||
if os.path.exists(out_file):
|
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:
|
if mode is None:
|
||||||
mode = int(hdrfields[1], 8)
|
mode = int(hdrfields[1], 8)
|
||||||
#
|
#
|
||||||
|
|
|
@ -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.
|
Loading…
Add table
Add a link
Reference in a new issue