From b4373c10df97887abafc2a9dc29ac44e1df0a83a Mon Sep 17 00:00:00 2001 From: Sebastion Date: Tue, 21 Jul 2026 08:04:30 +0100 Subject: [PATCH] fix: prevent path traversal in terminology excel upload (CWE-22) --- backend/apps/terminology/api/terminology.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/backend/apps/terminology/api/terminology.py b/backend/apps/terminology/api/terminology.py index 979cdf41..30415f99 100644 --- a/backend/apps/terminology/api/terminology.py +++ b/backend/apps/terminology/api/terminology.py @@ -177,9 +177,15 @@ async def upload_excel(trans: Trans, current_user: CurrentUser, file: UploadFile raise HTTPException(400, "Only support .xlsx/.xls") os.makedirs(path, exist_ok=True) - base_filename = f"{file.filename.split('.')[0]}_{hashlib.sha256(uuid.uuid4().bytes).hexdigest()[:10]}" - filename = f"{base_filename}.{file.filename.split('.')[1]}" - save_path = os.path.join(path, filename) + # Strip any directory components from the client-supplied filename to + # prevent path traversal (CWE-22). + safe_name = os.path.basename(file.filename) + name_root, name_ext = os.path.splitext(safe_name) + base_filename = f"{name_root}_{hashlib.sha256(uuid.uuid4().bytes).hexdigest()[:10]}" + filename = f"{base_filename}{name_ext}" + save_path = os.path.realpath(os.path.join(path, filename)) + if os.path.commonpath([save_path, os.path.realpath(path)]) != os.path.realpath(path): + raise HTTPException(400, "Invalid filename") with open(save_path, "wb") as f: f.write(await file.read()) @@ -262,7 +268,9 @@ def inner(): df = pd.DataFrame(md_data, columns=_fields_list) error_excel_filename = f"{base_filename}_error.xlsx" - save_error_path = os.path.join(path, error_excel_filename) + save_error_path = os.path.realpath(os.path.join(path, error_excel_filename)) + if os.path.commonpath([save_error_path, os.path.realpath(path)]) != os.path.realpath(path): + raise Exception("Invalid filename") # 保存 DataFrame 到 Excel df.to_excel(save_error_path, index=False)