Skip to content

Commit

Permalink
Merge commit from fork
Browse files Browse the repository at this point in the history
Fix path traversal in zip files
  • Loading branch information
MythicManiac authored Nov 5, 2024
2 parents 0b12777 + 7e64559 commit 007e4a6
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
14 changes: 11 additions & 3 deletions django/thunderstore/repository/package_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from thunderstore.repository.validation.manifest import validate_manifest
from thunderstore.repository.validation.markdown import validate_markdown
from thunderstore.repository.validation.zip import (
check_relative_paths,
check_duplicate_filenames,
check_unsafe_paths,
check_zero_offset,
)

Expand Down Expand Up @@ -127,14 +128,21 @@ def clean_file(self):
if unzip.testzip():
raise ValidationError("Corrupted zip file")

if check_relative_paths(unzip.infolist()):
raise ValidationError("Relative paths inside a zip are not allowed")
if check_unsafe_paths(unzip.infolist()):
raise ValidationError(
"There is an error with the zip's folder structure"
)

if not check_zero_offset(unzip.infolist()):
raise ValidationError(
"The zip includes bogus data at the beginning of the file."
)

if check_duplicate_filenames(unzip.infolist()):
raise ValidationError(
"The zip includes multiple files with the same file name."
)

try:
manifest = unzip.read("manifest.json")
self.validate_manifest(manifest)
Expand Down
25 changes: 23 additions & 2 deletions django/thunderstore/repository/validation/zip.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@
from zipfile import ZipInfo


def check_relative_paths(infolist: List[ZipInfo]) -> bool:
def check_unsafe_paths(infolist: List[ZipInfo]) -> bool:
for entry in infolist:
if entry.filename.startswith("..") or "/.." in entry.filename:
if (
entry.filename.startswith("..")
or entry.filename.startswith("/")
or entry.filename.startswith("\\")
or "/.." in entry.filename
or "//" in entry.filename
or "./" in entry.filename
or "\\.." in entry.filename
or "\\\\" in entry.filename
or ".\\" in entry.filename
or "/\\" in entry.filename
or "\\/" in entry.filename
):
return True
return False

Expand All @@ -14,3 +26,12 @@ def check_zero_offset(infolist: List[ZipInfo]) -> bool:
if entry.header_offset == 0:
return True
return False


def check_duplicate_filenames(infolist: List[ZipInfo]) -> bool:
filenames = set()
for entry in infolist:
if entry.filename.lower() in filenames:
return True
filenames.add(entry.filename.lower())
return False

0 comments on commit 007e4a6

Please sign in to comment.