复查修复(二): 同步模块与安全遗留

- 修复 remove_sync_source 引入的 stop_sync KeyError 回归(容错 get)
- stop_sync 不再删除存活线程条目(防双 worker);FTP 子目录递归传真名(不再 KeyError)
- 远程文件名统一 _safe_remote_name 校验(FTP/SFTP/HTTP 防路径穿越)
- temp 任务名加随机后缀防碰撞;temp 状态/线程完成后清理(防 sync_state.json 膨胀)
- save_sync_state 快照+原子写(临时文件+os.replace),持锁调用不死锁
- URL 打印脱敏(user:pass@ -> ***@)
- _need_sync_http size=0 不再全量重下(仅按存在性)
- cron 同一分钟去重;PyPI 进度只更新当前源
- v2 start_sync 不再把 bool 当 task_id
- UserRecord.to_dict 脱敏(不返回 password_hash/token),新增 to_dict_private/get_user_with_password
- config_hotreload 单配置源(set+persist 与热重载一致);server.py 用 get_all()
- 会话创建时顺带清理过期项;JSON stats/历史读改写加锁
- 解压目标目录先校验;FTP RETR 命令注入防护;rsync --delete 目标保护
- git/urlopen 补超时;cleanup_completed_tasks 删旧留新
This commit is contained in:
HYC Fixer
2026-09-02 00:39:12 +08:00
parent fc72759a92
commit 82875b710a
10 changed files with 957 additions and 810 deletions
+7 -2
View File
@@ -1297,6 +1297,10 @@ class APIv1:
return
extract_dir = os.path.join(self.config['base_dir'], target_dir)
# 先校验目标目录本身,防止 target_dir 含 .. 把目录建到 base_dir 外
if not is_safe_path(self.config['base_dir'], extract_dir):
handler.send_json_response({"error": "Invalid target directory"}, 403)
return
os.makedirs(extract_dir, exist_ok=True)
with zipfile.ZipFile(archive_path, 'r') as zipf:
@@ -1305,12 +1309,13 @@ class APIv1:
if not is_safe_path(self.config['base_dir'], member_path):
handler.send_json_response({"error": "Unsafe archive contents"}, 403)
return
members = zipf.namelist()
zipf.extractall(extract_dir)
# 同步提取的文件到数据库
if self.db:
extracted_files = []
for member in zipf.namelist():
for member in members:
member_path = os.path.join(extract_dir, member)
if os.path.isfile(member_path):
rel_member_path = os.path.relpath(member_path, self.config['base_dir']).replace("\\", "/")
@@ -1327,7 +1332,7 @@ class APIv1:
handler.send_json_response({
"operation": "extract",
"extract_dir": target_dir,
"extracted_files": len(zipf.namelist())
"extracted_files": len(members)
})
except Exception as e: