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()]

Reply via email to