binary-husky/gpt_academic · warning · Exception
Attempted Symlink in {member.name}
Error message
Attempted Symlink in {member.name} What it means
During tar/gz/bz2 extraction in handle_upload, every member is inspected first; hard links (islnk) and symlinks (issym) raise Exception('Attempted Symlink in {member.name}') before extractall runs. This blocks the classic zip-slip/symlink-overwrite attack where an archive member links to /etc/passwd or another extracted file to escape the destination.
Source
Thrown at shared_utils/handle_upload.py:141
file_extension = os.path.splitext(file_path)[1]
# 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":View on GitHub (pinned to d6bde0fa54)
Solutions
- Repack the archive without symlinks/hardlinks (replace links with copies of the target files), then re-upload.
- Verify with 'tar -tvf file.tar' — entries starting with 'l' or showing '->' are the culprits.
- Do not bypass the check on a public deployment; it is a security guard.
- If links are essential, extract manually after inspecting the archive.
Example fix
# shell: locate offending members # tar -tvf upload.tar | grep -E '^[hl]|->' # then replace symlinks with real copies and re-tar: # cp -L $(tar -tf upload.tar) . && tar -czf clean.tar.gz .
Defensive patterns
Strategy: validation
Validate before calling
import tarfile
def tar_has_links(path: str) -> list:
with tarfile.open(path, 'r:*') as t:
return [m.name for m in t.getmembers() if m.issym() or m.islnk()]
offenders = tar_has_links(upload_path)
if offenders:
reject_upload(f'archive contains links: {offenders[:5]}') Try / catch
try:
extract_archive(upload_path, dest_dir)
except Exception as e:
if 'Attempted Symlink' in str(e):
reject_upload('repack without symlinks')
else:
raise Prevention
- Pre-scan archives client-side with tar -tvf for link entries.
- Repack project sources with copies instead of symlinks before upload.
- Keep this guard enabled — it protects the extraction directory.
When it happens
Trigger: Uploading a .tar/.tar.gz/.tar.bz2 project archive (e.g. LaTeX source) that contains a symlink or hardlink entry; extraction is aborted entirely with the offending member name in the message.
Common situations: Legitimate LaTeX/source archives that use symlinks for shared figures or style files are rejected too (false positive by design); malicious uploads probing the extraction pipeline; archives created on macOS/Linux with 'ln -s' entries.
Related errors
- Attempted Path Traversal in {member.name}
- 输入文件的路径 ({path_or_url}) 存在,但位置非法。请将文件上传后再执行该任务。
- 输入文件的路径 ({path_or_url}) 存在,但属于其他用户。请将文件上传后再执行该任务。
AI-assisted analysis of binary-husky/gpt_academic@d6bde0fa54 (2026-08-14).
Data as JSON: /api/errors/87c7dad3c8a70f2b.
Report an issue: GitHub.