|
1 | | -// Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. |
| 1 | +// Copyright (c) 2021-2026, NVIDIA CORPORATION. All rights reserved. |
2 | 2 | // |
3 | 3 | // Redistribution and use in source and binary forms, with or without |
4 | 4 | // modification, are permitted provided that the following conditions |
@@ -115,11 +115,24 @@ ExtractTarFile(std::string& archive_path, std::string& dst_path) |
115 | 115 | } |
116 | 116 |
|
117 | 117 | struct archive_entry* entry; |
118 | | - int flags = ARCHIVE_EXTRACT_TIME; |
| 118 | + // Reject archive entries that could write outside of `dst_path`. |
| 119 | + // This includes: |
| 120 | + // - Parent directory traversal (e.g., "../") |
| 121 | + // - Absolute paths |
| 122 | + // - Writes through symlinks present in the archive |
| 123 | + int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_SECURE_NODOTDOT | |
| 124 | + ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS | |
| 125 | + ARCHIVE_EXTRACT_SECURE_SYMLINKS; |
119 | 126 |
|
120 | 127 | struct archive* input_archive = archive_read_new(); |
121 | 128 | struct archive* output_archive = archive_write_disk_new(); |
122 | | - archive_write_disk_set_options(output_archive, flags); |
| 129 | + if (archive_write_disk_set_options(output_archive, flags) != ARCHIVE_OK) { |
| 130 | + std::string err = std::string("archive_write_disk_set_options() failed: ") + |
| 131 | + archive_error_string(output_archive); |
| 132 | + archive_read_free(input_archive); |
| 133 | + archive_write_free(output_archive); |
| 134 | + throw PythonBackendException(err); |
| 135 | + } |
123 | 136 |
|
124 | 137 | archive_read_support_filter_gzip(input_archive); |
125 | 138 | archive_read_support_format_tar(input_archive); |
|
0 commit comments