2026-07-13 11:52:43 +08:00
|
|
|
|
---
|
|
|
|
|
|
id: T-616
|
|
|
|
|
|
title: 自动升级安全下载校验与同盘暂存
|
|
|
|
|
|
phase: 8
|
|
|
|
|
|
deps: [T-615]
|
2026-07-13 12:02:47 +08:00
|
|
|
|
status: DONE
|
2026-07-13 11:52:43 +08:00
|
|
|
|
created: 2026-07-13
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 问题 / 背景
|
|
|
|
|
|
|
|
|
|
|
|
自动升级不能把远程zip直接交给更新器。客户端必须先完成可信地址限制、流式下载、大小/hash校验、防zip路径穿越、安全解压、包内版本与manifest逐文件校验;任何一步失败都不能碰当前程序文件。
|
|
|
|
|
|
|
|
|
|
|
|
更新临时文件不能混进用户业务数据 `data/`。本任务使用安装目录同级管理区 `<安装目录>/.cmshopee-update/`,既与程序在同一磁盘便于后续目录切换,也与账号、SQLite、图片和密钥完全隔离。
|
|
|
|
|
|
|
|
|
|
|
|
## 方案
|
|
|
|
|
|
|
|
|
|
|
|
1. 新增 `app/update_installer.py` 纯逻辑模块,定义自动安装元数据、下载结果、暂存结果和中文错误类型;不得依赖Qt控件。
|
|
|
|
|
|
2. 只接受HTTPS下载地址。下载主机采用客户端受信任域名白名单;重定向只能落在同一白名单内,禁止降级HTTP、`file://`、内网地址和任意第三方跳转。
|
|
|
|
|
|
3. 流式下载到 `.cmshopee-update/downloads/<version>.zip.part`,持续校验累计字节数,完成后要求与 `size_bytes` 完全一致、SHA-256严格一致,再原子改名为 `.zip`。包大小硬上限建议512 MiB;超限、磁盘不足、中断或取消时保留当前版本,清理不完整part文件。
|
|
|
|
|
|
4. 安全解压到 `.cmshopee-update/staging/<version>-<随机值>/`。解压前逐项拒绝绝对路径、盘符/UNC、`..`、符号链接、Windows保留名、NTFS ADS冒号、尾随点/空格、大小写不敏感重复目标;限制文件数不超过20000、解压总量不超过2 GiB,并限制异常压缩比。
|
|
|
|
|
|
5. 解压后严格验证 `version.txt`、`package-manifest.json`、`cmshopee.exe` 和 `_internal/`;版本、包格式、更新器协议必须与服务端元数据一致。按manifest逐文件复算大小和SHA-256,拒绝manifest未声明的程序文件和缺失文件。
|
|
|
|
|
|
6. 本地写入 `pending.json` 只记录版本、安装根、暂存根、hash和阶段,不记录URL查询参数、密钥或用户数据路径。下一次启动可识别已经完整校验的暂存包,避免重复下载;无效/不完整pending必须清理后重新下载。
|
|
|
|
|
|
7. 失败消息对用户保持中文概述,远程URL、内部路径、堆栈写入脱敏诊断日志,不直接展示。
|
|
|
|
|
|
|
|
|
|
|
|
## 验收要点
|
|
|
|
|
|
|
|
|
|
|
|
- 正常zip能下载、校验并暂存,当前 `cmshopee.exe`、`_internal/` 和 `data/` 完全不变。
|
|
|
|
|
|
- hash为空、格式错误、不匹配,大小不匹配,HTTP/非白名单地址和越权重定向均拒绝安装。
|
|
|
|
|
|
- zip slip、符号链接、大小写重复、保留名、ADS、zip bomb和manifest缺失/篡改均被自动化测试阻断。
|
|
|
|
|
|
- 下载中断后不会把 `.part` 当完整包;已验证pending可在重启后复用,不重复下载。
|
|
|
|
|
|
- 更新目录始终位于 `.cmshopee-update/`,不创建 `data/updates`,不读取用户业务数据。
|
|
|
|
|
|
|
|
|
|
|
|
## 测试要求
|
|
|
|
|
|
|
|
|
|
|
|
- 新增 `tests/test_update_installer.py`,使用临时目录和本地可控响应覆盖成功、取消、网络失败、所有安全拒绝路径及pending恢复。
|
|
|
|
|
|
- 运行ruff、compileall、完整unittest和 `git diff --check`;不依赖真实线上下载地址。
|
|
|
|
|
|
|
|
|
|
|
|
## 边界(不改什么)
|
|
|
|
|
|
|
|
|
|
|
|
- 不启动独立更新器,不替换程序,不自动重启。
|
|
|
|
|
|
- 不修改当前T-544强制升级GUI;GUI接入由T-618完成。
|
|
|
|
|
|
- 不读取、移动、覆盖或清理 `data/`。
|
|
|
|
|
|
|
|
|
|
|
|
## 执行记录
|
|
|
|
|
|
|
2026-07-13 12:02:47 +08:00
|
|
|
|
- 2026-07-13:新增无Qt依赖的 `app/update_installer.py`,实现受信任HTTPS下载、同盘part暂存、大小/hash校验、安全zip解压、manifest逐文件复核及可复用 `pending.json`。
|
|
|
|
|
|
- 2026-07-13:补齐版本接口自动安装元数据透传;所有失败均发生在当前程序替换前,取消与无效pending会清理不完整状态,`data/` 不参与更新。
|
|
|
|
|
|
- 2026-07-13:干净worktree验证通过:ruff、compileall、完整unittest(400项)和 `git diff --check`。
|