This repository has been archived on 2020-03-24. You can view files and clone it, but cannot push or open issues or pull requests.
quay/util/safetar.py

52 lines
1.6 KiB
Python

import os.path
import logging
import copy
import operator
logger = logging.getLogger(__name__)
def safe_extractall(tar, path):
"""Extract all members from the archive to the current working
directory and set owner, modification time and permissions on
directories afterwards. `path' specifies a different directory
to extract to. `members' is optional and must be a subset of the
list returned by getmembers().
"""
abs_extract_path = os.path.abspath(path)
def is_member_safe(member):
""" Returns True if the member is safe, False otherwise. """
if member.issym():
link_tar_path = os.path.dirname(member.path)
abs_link_path = os.path.abspath(os.path.join(path, link_tar_path, member.linkpath))
if not abs_link_path.startswith(abs_extract_path):
logger.warning('Filtering symlink outside of extract dir: %s', member.linkpath)
return False
elif member.isblk():
logger.warning('Filtering block device from tarfile: %s', member.path)
return False
return True
directories = []
for tarinfo in tar:
if is_member_safe(tarinfo):
if tarinfo.isdir():
# Extract directories with a safe mode.
directories.append(tarinfo)
tarinfo = copy.copy(tarinfo)
tarinfo.mode = 0700
tar.extract(tarinfo, path)
# Reverse sort directories.
directories.sort(key=operator.attrgetter('name'))
directories.reverse()
# Set correct owner, mtime and filemode on directories.
for tarinfo in directories:
dirpath = os.path.join(path, tarinfo.name)
tar.chown(tarinfo, dirpath)
tar.utime(tarinfo, dirpath)
tar.chmod(tarinfo, dirpath)