binary-husky/gpt_academic · warning · Exception

Attempted Path Traversal in {member.name}

Error message

Attempted Path Traversal in {member.name}

What it means

Companion check to error 198: for each tar member, member.name is normalized, joined with dest_dir, made absolute, and required to stay inside dest_dir + os.sep; otherwise extraction aborts with Exception('Attempted Path Traversal in {member.name}'). This stops '../'-style members from writing outside the extraction directory (zip-slip).

Source

Thrown at shared_utils/handle_upload.py:143

    # Extract the archive based on its extension
    if file_extension == ".zip":
        with zipfile.ZipFile(file_path, "r") as zipobj:
            zipobj._extract_member = lambda a,b,c: zip_extract_member_new(zipobj, a,b,c)    # 修复中文乱码的问题
            zipobj.extractall(path=dest_dir)
            logger.info("Successfully extracted zip archive to {}".format(dest_dir))

    elif file_extension in [".tar", ".gz", ".bz2"]:
        try:
            with tarfile.open(file_path, "r:*") as tarobj:
                # 清理提取路径,移除任何不安全的元素
                for member in tarobj.getmembers():
                    member_path = os.path.normpath(member.name)
                    full_path = os.path.join(dest_dir, member_path)
                    full_path = os.path.abspath(full_path)
                    if member.islnk() or member.issym():
                        raise Exception(f"Attempted Symlink in {member.name}")
                    if not full_path.startswith(os.path.abspath(dest_dir) + os.sep):
                        raise Exception(f"Attempted Path Traversal in {member.name}")

                tarobj.extractall(path=dest_dir)
                logger.info("Successfully extracted tar archive to {}".format(dest_dir))
        except tarfile.ReadError as e:
            if file_extension == ".gz":
                # 一些特别奇葩的项目,是一个gz文件,里面不是tar,只有一个tex文件
                import gzip
                with gzip.open(file_path, 'rb') as f_in:
                    with open(os.path.join(dest_dir, 'main.tex'), 'wb') as f_out:
                        f_out.write(f_in.read())
            else:
                raise e

    # 第三方库,需要预先pip install rarfile
    # 此外,Windows上还需要安装winrar软件,配置其Path环境变量,如"C:\Program Files\WinRAR"才可以
    elif file_extension == ".rar":
        try:
            import rarfile  # 用来检查rarfile是否安装,不要删除

View on GitHub (pinned to d6bde0fa54)

Solutions

  1. Do not upload the archive; inspect it ('tar -tvf') and remove/rewrite entries with '..' or leading '/' components.
  2. Repack cleanly from a fresh directory (tar -czf from inside the source dir avoids absolute prefixes).
  3. Treat repeated occurrences as a sign of a hostile file — do not whitelist.

Example fix

# shell: inspect and repack safely
# tar -tvf upload.tar                 # look for ../ or leading /
# mkdir clean && tar -xzf upload.tar -C clean  # only after manual review
# (cd clean && tar -czf clean.tar.gz .)
Defensive patterns

Strategy: validation

Validate before calling

import tarfile, os

def tar_members_escape(dest_dir: str, path: str) -> list:
    root = os.path.abspath(dest_dir) + os.sep
    with tarfile.open(path, 'r:*') as t:
        return [m.name for m in t.getmembers()
                if not (os.path.abspath(os.path.join(dest_dir, os.path.normpath(m.name))).startswith(root))]

if tar_members_escape(dest_dir, upload_path):
    reject_upload('archive contains path traversal entries')

Try / catch

try:
    extract_archive(upload_path, dest_dir)
except Exception as e:
    if 'Attempted Path Traversal' in str(e):
        quarantine_upload(upload_path)  # suspicious file — flag it
    else:
        raise

Prevention

When it happens

Trigger: Uploading a tar archive containing member names like '../../etc/cron.d/x' or absolute paths that, after normpath/abspath, resolve outside the destination upload directory.

Common situations: Malicious crafted archives targeting the upload handler; rarely, archives built with unusual tooling that emits './'-prefixed or absolute entry names that normalize outside dest_dir; the guard is intentional and should not fire for normal archives.

Related errors


AI-assisted analysis of binary-husky/gpt_academic@d6bde0fa54 (2026-08-14). Data as JSON: /api/errors/092359b37ee68e39. Report an issue: GitHub.