8000 [4.2.x] Fixed CVE-2025-59682 -- Fixed potential partial directory-tra… · django/django@9504bba · GitHub
[go: up one dir, main page]

Skip to content

Commit 9504bba

Browse files
sarahboycejacobtylerwalls
authored andcommitted
[4.2.x] Fixed CVE-2025-59682 -- Fixed potential partial directory-traversal via archive.extract().
Thanks stackered for the report. Follow up to 05413af. Backport of 924a0c0 from main.
1 parent 38d9ef8 commit 9504bba

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

django/utils/archive.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,11 @@ def has_leading_dir(self, paths):
144144
def target_filename(self, to_path, name):
145145
target_path = os.path.abspath(to_path)
146146
filename = os.path.abspath(os.path.join(target_path, name))
147-
if not filename.startswith(target_path):
147+
try:
148+
if os.path.commonpath([target_path, filename]) != target_path:
149+
raise SuspiciousOperation("Archive contains invalid path: '%s'" % name)
150+
except ValueError:
151+
# Different drives on Windows raises ValueError.
148152
raise SuspiciousOperation("Archive contains invalid path: '%s'" % name)
149153
return filename
150154

docs/releases/4.2.25.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@ CVE-2025-59681: Potential SQL injection in ``QuerySet.annotate()``, ``alias()``,
1515
to SQL injection in column aliases, using a suitably crafted dictionary, with
1616
dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
1717
:cve:`2022-28346`).
18+
19+
CVE-2025-59682: Potential partial directory-traversal via ``archive.extract()``
20+
===============================================================================
21+
22+
The ``django.utils.archive.extract()`` function, used by
23+
:option:`startapp --template` and :option:`startproject --template`, allowed
24+
partial directory-traversal via an archive with file paths sharing a common
25+
prefix with the target directory (follow up to :cve:`2021-3281`).

tests/utils_tests/test_archive.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44
import tempfile
55
import unittest
6+
import zipfile
67

78
from django.core.exceptions import SuspiciousOperation
89
from django.test import SimpleTestCase
@@ -96,3 +97,21 @@ def test_extract_function_traversal(self):
9697
with self.subTest(entry), tempfile.TemporaryDirectory() as tmpdir:
9798
with self.assertRaisesMessage(SuspiciousOperation, msg % invalid_path):
9899
archive.extract(os.path.join(archives_dir, entry), tmpdir)
100+
101+
def test_extract_function_traversal_startswith(self):
102+
with tempfile.TemporaryDirectory() as tmpdir:
103+
base = os.path.abspath(tmpdir)
104+
tarfile_handle = tempfile.NamedTemporaryFile(suffix=".zip", delete=False)
105+
tar_path = tarfile_handle.name
106+
tarfile_handle.close()
107+
self.addCleanup(os.remove, tar_path)
108+
109+
malicious_member = os.path.join(base + "abc", "evil.txt")
110+
with zipfile.ZipFile(tar_path, "w") as zf:
111+
zf.writestr(malicious_member, "evil\n")
112+
zf.writestr("test.txt", "data\n")
113+
114+
with self.assertRaisesMessage(
115+
SuspiciousOperation, "Archive contains invalid path"
116+
):
117+
archive.extract(tar_path, base)

0 commit comments

Comments
 (0)
0