gh-99889: Fix directory traversal security flaw in uu.decode() (#104096) · python/cpython@0aeda29 (original) (raw)

File tree

3 files changed

lines changed

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -147,6 +147,34 @@ def test_newlines_escaped(self):
147 147 uu.encode(inp, out, filename)
148 148 self.assertIn(safefilename, out.getvalue())
149 149
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 +
150 178 class UUStdIOTest(unittest.TestCase):
151 179
152 180 def setUp(self):
Original file line number Diff line number Diff line change
@@ -133,7 +133,14 @@ def decode(in_file, out_file=None, mode=None, quiet=False):
133 133 # If the filename isn't ASCII, what's up with that?!?
134 134 out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii")
135 135 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')
137 144 if mode is None:
138 145 mode = int(hdrfields[1], 8)
139 146 #
Original file line number Diff line number Diff 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.