Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 15d98b4

Browse filesBrowse files
samcarroll42miss-islington
authored andcommitted
pythongh-99889: Fix directory traversal security flaw in uu.decode() (pythonGH-104096)
* Fix directory traversal security flaw in uu.decode() * also check absolute paths and os.altsep * Add a regression test. --------- (cherry picked from commit 0aeda29) Co-authored-by: Sam Carroll <70000253+samcarroll42@users.noreply.github.com> Co-authored-by: Gregory P. Smith <greg@krypto.org> [Google]
1 parent 97e1e43 commit 15d98b4
Copy full SHA for 15d98b4

File tree

3 files changed

+38
-1
lines changed
Filter options

3 files changed

+38
-1
lines changed

‎Lib/test/test_uu.py

Copy file name to clipboardExpand all lines: Lib/test/test_uu.py
+28Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,34 @@ def test_newlines_escaped(self):
147147
uu.encode(inp, out, filename)
148148
self.assertIn(safefilename, out.getvalue())
149149

150+
def test_no_directory_traversal(self):
151+
relative_bad = b"""\
152+
begin 644 ../../../../../../../../tmp/test1
153+
$86)C"@``
154+
`
155+
end
156+
"""
157+
with self.assertRaisesRegex(uu.Error, 'directory'):
158+
uu.decode(io.BytesIO(relative_bad))
159+
if os.altsep:
160+
relative_bad_bs = relative_bad.replace(b'/', b'\\')
161+
with self.assertRaisesRegex(uu.Error, 'directory'):
162+
uu.decode(io.BytesIO(relative_bad_bs))
163+
164+
absolute_bad = b"""\
165+
begin 644 /tmp/test2
166+
$86)C"@``
167+
`
168+
end
169+
"""
170+
with self.assertRaisesRegex(uu.Error, 'directory'):
171+
uu.decode(io.BytesIO(absolute_bad))
172+
if os.altsep:
173+
absolute_bad_bs = absolute_bad.replace(b'/', b'\\')
174+
with self.assertRaisesRegex(uu.Error, 'directory'):
175+
uu.decode(io.BytesIO(absolute_bad_bs))
176+
177+
150178
class UUStdIOTest(unittest.TestCase):
151179

152180
def setUp(self):

‎Lib/uu.py

Copy file name to clipboard
100755100644
Expand all lines: Lib/uu.py
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,14 @@ def decode(in_file, out_file=None, mode=None, quiet=False):
133133
# If the filename isn't ASCII, what's up with that?!?
134134
out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii")
135135
if os.path.exists(out_file):
136-
raise Error('Cannot overwrite existing file: %s' % out_file)
136+
raise Error(f'Cannot overwrite existing file: {out_file}')
137+
if (out_file.startswith(os.sep) or
138+
f'..{os.sep}' in out_file or (
139+
os.altsep and
140+
(out_file.startswith(os.altsep) or
141+
f'..{os.altsep}' in out_file))
142+
):
143+
raise Error(f'Refusing to write to {out_file} due to directory traversal')
137144
if mode is None:
138145
mode = int(hdrfields[1], 8)
139146
#
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed a security in flaw in :func:`uu.decode` that could allow for
2+
directory traversal based on the input if no ``out_file`` was specified.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.