3.4 KiB
3.4 KiB
id, title, phase, deps, status, created
| id | title | phase | deps | status | created | |
|---|---|---|---|---|---|---|
| T-616 | 自动升级安全下载校验与同盘暂存 | 8 |
|
TODO | 2026-07-13 |
问题 / 背景
自动升级不能把远程zip直接交给更新器。客户端必须先完成可信地址限制、流式下载、大小/hash校验、防zip路径穿越、安全解压、包内版本与manifest逐文件校验;任何一步失败都不能碰当前程序文件。
更新临时文件不能混进用户业务数据 data/。本任务使用安装目录同级管理区 <安装目录>/.cmshopee-update/,既与程序在同一磁盘便于后续目录切换,也与账号、SQLite、图片和密钥完全隔离。
方案
- 新增
app/update_installer.py纯逻辑模块,定义自动安装元数据、下载结果、暂存结果和中文错误类型;不得依赖Qt控件。 - 只接受HTTPS下载地址。下载主机采用客户端受信任域名白名单;重定向只能落在同一白名单内,禁止降级HTTP、
file://、内网地址和任意第三方跳转。 - 流式下载到
.cmshopee-update/downloads/<version>.zip.part,持续校验累计字节数,完成后要求与size_bytes完全一致、SHA-256严格一致,再原子改名为.zip。包大小硬上限建议512 MiB;超限、磁盘不足、中断或取消时保留当前版本,清理不完整part文件。 - 安全解压到
.cmshopee-update/staging/<version>-<随机值>/。解压前逐项拒绝绝对路径、盘符/UNC、..、符号链接、Windows保留名、NTFS ADS冒号、尾随点/空格、大小写不敏感重复目标;限制文件数不超过20000、解压总量不超过2 GiB,并限制异常压缩比。 - 解压后严格验证
version.txt、package-manifest.json、cmshopee.exe和_internal/;版本、包格式、更新器协议必须与服务端元数据一致。按manifest逐文件复算大小和SHA-256,拒绝manifest未声明的程序文件和缺失文件。 - 本地写入
pending.json只记录版本、安装根、暂存根、hash和阶段,不记录URL查询参数、密钥或用户数据路径。下一次启动可识别已经完整校验的暂存包,避免重复下载;无效/不完整pending必须清理后重新下载。 - 失败消息对用户保持中文概述,远程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/。
执行记录
(完成后记录实现、验证命令与结果。)