|
10 | 10 | from notebook.base.handlers import IPythonHandler |
11 | 11 | from netpyne_ui.constants import ALLOWED_EXTENSIONS, UPLOAD_FOLDER_PATH |
12 | 12 |
|
| 13 | + |
13 | 14 | def allowed_file(filename, allowed_extensions=ALLOWED_EXTENSIONS): |
14 | 15 | return '.' in filename and \ |
15 | 16 | filename.rsplit('.', 1)[1].lower() in allowed_extensions |
@@ -43,6 +44,23 @@ def get_file_paths(handler): |
43 | 44 | return file_paths |
44 | 45 |
|
45 | 46 |
|
| 47 | +def is_within_directory(directory, target): |
| 48 | + abs_directory = os.path.abspath(directory) |
| 49 | + abs_target = os.path.abspath(target) |
| 50 | + |
| 51 | + prefix = os.path.commonprefix([abs_directory, abs_target]) |
| 52 | + |
| 53 | + return prefix == abs_directory |
| 54 | + |
| 55 | + |
| 56 | +def safe_extract_tar(tar, path=".", members=None, *, numeric_owner=False): |
| 57 | + for member in tar.getmembers(): |
| 58 | + member_path = os.path.join(path, member.name) |
| 59 | + if not is_within_directory(path, member_path): |
| 60 | + raise Exception("Attempted Path Traversal in Tar File") |
| 61 | + tar.extractall(path, members, numeric_owner=numeric_owner) |
| 62 | + |
| 63 | + |
46 | 64 | class NetPyNEController: # pytest: no cover |
47 | 65 |
|
48 | 66 | @post('/uploads') |
@@ -74,7 +92,7 @@ def uploads(handler: IPythonHandler): |
74 | 92 |
|
75 | 93 | elif filename.endswith('.tar.gz'): |
76 | 94 | with tarfile.open(file_path, mode='r:gz') as tar: |
77 | | - tar.extractall(UPLOAD_FOLDER_PATH) |
| 95 | + safe_extract_tar(tar, UPLOAD_FOLDER_PATH) |
78 | 96 |
|
79 | 97 | elif filename.endswith('.gz'): |
80 | 98 | with gzip.open(file_path, "rb") as gz, open(file_path.replace('.gz', ''), 'wb') as ff: |
|
0 commit comments