This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit e53e9e322cbaafc59ed77055bdc1e47c08bc3cbe
Author: Dave Brondsema <[email protected]>
AuthorDate: Tue May 19 12:35:26 2026 -0400

    [#8607] test for save_attachments (export) path handling
---
 Allura/allura/tests/test_app.py | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/Allura/allura/tests/test_app.py b/Allura/allura/tests/test_app.py
index 913840315..6b3b73d03 100644
--- a/Allura/allura/tests/test_app.py
+++ b/Allura/allura/tests/test_app.py
@@ -21,6 +21,8 @@
 import pytest
 from formencode import validators as fev
 from textwrap import dedent
+import tempfile
+import os.path
 
 from alluratest.controller import setup_unit_test
 from allura import app
@@ -171,3 +173,33 @@ def test_handle_artifact_unicode(self, qg):
         for p in [p for p in msg['parts'] if p['payload'] is not None]:
             # filter here mimics logic in `route_email`
             a.handle_artifact_message(ticket, p)
+
+    def test_save_attachments_path_traversal_protection(self):
+        a = app.Application(c.project, c.app.config)
+        export_dir = tempfile.mkdtemp()
+
+        class FakeAttachment:
+            def __init__(self, filename, data):
+                self.filename = filename
+                self._data = data
+
+            def rfile(self):
+                from io import BytesIO
+                return BytesIO(self._data)
+
+        # Test with a malicious filename containing path traversal
+        malicious_name = '../../allura-test-case/foobar'
+        attachments = [FakeAttachment(malicious_name, b'evil data')]
+        a.save_attachments(export_dir, attachments)
+
+        # The file should be written as a basename, not traverse directories
+        expected_file = os.path.join(export_dir, 'foobar')
+        assert os.path.exists(expected_file)
+
+        # Verify the traversal path was NOT created
+        traversal_path = os.path.join(export_dir, '..', '..', 
'allura-test-case', 'foobar')
+        assert not os.path.exists(traversal_path)
+
+        # Verify file contents
+        with open(expected_file, 'rb') as f:
+            assert f.read() == b'evil data'

Reply via email to