This is an automated email from the ASF dual-hosted git repository. micafer pushed a commit to branch fix_storage_path in repository https://gitbox.apache.org/repos/asf/libcloud.git
commit 4eb100a0ad78f8101ad68fb0d282411f158d1a3d Author: Miguel Caballer <[email protected]> AuthorDate: Thu Nov 5 10:10:37 2026 +0100 Fix security issue path traversal --- libcloud/storage/base.py | 2 +- libcloud/test/storage/test_base.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libcloud/storage/base.py b/libcloud/storage/base.py index 42b80f6fc..0c872bb83 100644 --- a/libcloud/storage/base.py +++ b/libcloud/storage/base.py @@ -763,7 +763,7 @@ class StorageDriver(BaseDriver): raise LibcloudError(value="Path %s does not exist" % (destination_path), driver=self) if not base_name: - file_path = pjoin(destination_path, obj.name) + file_path = pjoin(destination_path, os.path.basename(obj.name)) else: file_path = destination_path diff --git a/libcloud/test/storage/test_base.py b/libcloud/test/storage/test_base.py index ced1f9de7..f48e10374 100644 --- a/libcloud/test/storage/test_base.py +++ b/libcloud/test/storage/test_base.py @@ -16,6 +16,8 @@ import sys import errno import hashlib +import os +import tempfile from io import BytesIO from unittest import mock from unittest.mock import Mock @@ -53,6 +55,22 @@ class BaseStorageTests(unittest.TestCase): self.driver1.strict_mode = False self.driver1.strict_mode = False + def test_save_object_confines_provider_name_to_destination_directory(self): + with tempfile.TemporaryDirectory() as temp_dir: + destination_path = os.path.join(temp_dir, "downloads") + os.sep + os.mkdir(destination_path) + outside_path = os.path.join(temp_dir, "evil") + response = Mock() + response._response.iter_content.return_value = [b"PWNED"] + obj = Mock(size=5) + obj.name = "../../evil" + + self.driver1._save_object(response, obj, destination_path) + + self.assertFalse(os.path.exists(outside_path)) + with open(os.path.join(destination_path, "evil"), "rb") as file_handle: + self.assertEqual(file_handle.read(), b"PWNED") + def test__upload_object_iterator_must_have_next_method(self): valid_iterators = [BytesIO(b("134")), StringIO("bar")] invalid_iterators = ["foobar", "", False, True, 1, object()]
