Skip to content

Instantly share code, notes, and snippets.

@meisterluk
Created October 5, 2022 01:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save meisterluk/2ec63a2b593c1840b23bfc4ebe44a347 to your computer and use it in GitHub Desktop.
Save meisterluk/2ec63a2b593c1840b23bfc4ebe44a347 to your computer and use it in GitHub Desktop.
zipfile's extractall method with a path check that the target folder is the prefix after utilizing os.path.normpath
import os.path
import zipfile
# tested with python 3.8.10
def secure_zipfile_extractall(zip_filedesc, target_directory):
"""Copy all files recorded in zipfile `zip_filedesc`
to the directory `target_directory`, but prevent malicious filepaths
like `../../../etc/hosts` by using os.path.normpath
"""
if not target_directory.endswith('/'):
target_directory = target_directory + '/'
def is_secure(member_path):
if member_path.startswith('/') or member_path.startswith('\\'):
return False
if '//' in member_path or '\\\\' in member_path:
return False
target_path = os.path.join(target_directory, member_path)
return os.path.normpath(target_path).startswith(target_directory)
zip_filepaths = filter(is_secure, zip_filedesc.namelist())
for filepath in zip_filepaths:
zip_filedesc.extract(filepath, path=target_directory)
# Example:
with zipfile.ZipFile("archive.zip", 'r') as zfd:
## insecure way:
#zfd.extractall(path=tmp_folder)
# secure way:
secure_zipfile_extractall(zfd, tmp_folder)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment