Prototype secure ZIP extraction (T-102)
This commit is contained in:
@@ -147,6 +147,8 @@ soft_quay/
|
||||
|
||||
必须防止:绝对路径、`../` 穿越、符号链接逃逸、写入其他软件目录、覆盖 data 与 licenses、运行中强替换 EXE、未验证包被执行、解压数量/体积/压缩比无上限、包内自动执行脚本。
|
||||
|
||||
Phase 1 ZIP 原型采用“两阶段解压”:先完整预检中央目录、协议顶层、路径、类型、重复项、entrypoint 与资源上限,全部通过后才创建新的 staging 并只写 `payload/`;任一复制/CRC 失败删除本次 staging。原型默认限制见 [api.md](api.md),T-302 正式整合时复核。
|
||||
|
||||
盒子自更新由独立 `SoftBoxUpdater.exe` 完成(传入 PID、暂存目录、目标目录;等待退出→备份→切换→启动新版→失败恢复)。
|
||||
|
||||
授权:平台层采集多个稳定硬件标识 → 清洗生成 machine_hash(不保存原始序列号/MAC)→ 服务端 Ed25519 私钥签发许可证 → 客户端内置公钥离线验签;许可证与程序文件、用户配置分开保存;子软件必须独立再次验证,不能只信盒子。
|
||||
|
||||
@@ -119,6 +119,14 @@ json-parser_1.4.2_windows_amd64.zip
|
||||
|
||||
绝对路径;`../` 穿越;符号链接/重解析点逃出 staging;写入其他软件或盒子目录;覆盖 `data/` 与 `licenses/`;包内自动执行脚本(install.bat/PowerShell 钩子);未验证 SHA-256/签名的包被执行;解压文件数、总体积或压缩比无上限;entrypoint 指向 payload 之外。
|
||||
|
||||
T-102 Phase 1 原型进一步固定:
|
||||
|
||||
- ZIP 名称只接受 UTF-8 `/` 分隔的规范相对路径;拒绝反斜杠、盘符、冒号/NTFS ADS、NUL、`.`/`..` 和大小写折叠后的重复输出路径。
|
||||
- 顶层只允许必需的 `app.json`、可选 `files.json` 与 `payload/`;只把 `payload/` 内容写入全新的 staging。
|
||||
- 拒绝符号链接、设备/管道等特殊文件和加密条目。
|
||||
- 原型默认上限:10,000 个条目、总展开 4 GiB、单条及总体压缩比 200:1。T-302 按真实包体分布复核后再冻结。
|
||||
- entrypoint 使用 payload 内相对路径表示,不得自带 `payload/` 前缀,且必须精确对应 ZIP 中的普通文件。
|
||||
|
||||
### 2.4 安装记录 installed-app.json(本地)
|
||||
|
||||
记录实际安装的软件 ID、版本、架构、channel 和文件清单;与 `current/`、`staging/`、`backup/` 同级存放于 `apps/<id>/`。
|
||||
|
||||
@@ -13,24 +13,24 @@
|
||||
## 当前快照
|
||||
|
||||
- 日期:2026-07-16
|
||||
- 阶段:M2 进行中(Phase 1 的 T-101 清单验签与缓存回退原型已完成)
|
||||
- 阶段:M2 进行中(Phase 1 的 T-101 清单验签与 T-102 ZIP 安全解压原型已完成)
|
||||
- 技术栈:根 Go workspace 纳入 core/app-modern/app-win7 三模块;`app-win7/go.work` 隔离 Go 1.20.14 构建;modern Gio v0.10.1 与 win7 Gio v0.6.0 已实际接入
|
||||
- 生产代码:core 已有状态/事件 runtime 与 Catalog Ed25519 验签、受限规范 JSON、验证后缓存回退原型;modern/win7 均可打开最小 AppShell
|
||||
- 测试:core 覆盖状态/事件、Catalog 篡改/伪造/歧义输入、缓存回退和文件缓存恢复;两个 app 覆盖 AppShell 与平台 stub
|
||||
- 数据:`testdata/catalog/` 已有公开虚构的合法 payload、篡改 payload 与伪造签名样例
|
||||
- 生产代码:core 已有状态/事件、Catalog 验签/缓存原型与 ZIP 两阶段安全解压器;modern/win7 均可打开最小 AppShell
|
||||
- 测试:core 覆盖 Catalog 攻击/缓存与 ZIP 路径、类型、资源上限、entrypoint、CRC 失败清理;两个 app 覆盖 AppShell 与平台 stub
|
||||
- 数据:`testdata/catalog/` 有公开虚构清单样例;`testdata/zip/` 记录运行时生成的 ZIP 攻击矩阵
|
||||
- 标准启动路径:`./init.sh` / `./init.ps1`(同步依赖、执行完整 Phase 0 闸门、打印双目标构建命令)
|
||||
- 标准验证路径:`bash scripts/verify_phase0.sh` / `./scripts/verify_phase0.ps1`
|
||||
- 版本管理:git 已初始化,main 分支,远端 origin 为 Gitea `opc/soft_quay`;harness 文档已提交
|
||||
- 当前 blocker:无;下一步按路线图落成并领取 T-102
|
||||
- 当前 blocker:无;下一步按路线图落成并领取 T-103
|
||||
|
||||
## 当前目录要点
|
||||
|
||||
| 路径 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `docs/` | 已有 | harness coding 文档集(本次初始化完成) |
|
||||
| `docs/tasks/` | 已有 | Phase 0 四项与 T-101 已完成;T-102 待按路线图落成 |
|
||||
| `docs/tasks/` | 已有 | Phase 0 四项与 T-101/T-102 已完成;T-103 待按路线图落成 |
|
||||
| `scripts/` | 已有 | harness 治理、core 边界、Go 版本检查与 Phase 0 双平台验证入口 |
|
||||
| `core/` | 已建 | Go 1.20 兼容共享模块;已有状态/事件与 Catalog 验签/缓存原型 |
|
||||
| `core/` | 已建 | Go 1.20 兼容;已有状态/事件、Catalog 验签/缓存和 ZIP 安全解压原型 |
|
||||
| `app-modern/` | 已建 | Go 1.25.0 + Gio v0.10.1;可打开 Modern AppShell |
|
||||
| `app-win7/` | 已建 | Go 1.20 + Gio v0.6.0;可打开带 Legacy 标识的 AppShell |
|
||||
| `schemas/` | 待建 | 协议 JSON Schema(T-201) |
|
||||
@@ -40,9 +40,9 @@
|
||||
|
||||
任务状态以 `docs/tasks/` 各任务文件 frontmatter 的 `status` 为准。本节只写项目级摘要:
|
||||
|
||||
- 已完成:Phase 0 的 `T-001`~`T-004`;Phase 1 的 `T-101`。
|
||||
- 已完成:Phase 0 的 `T-001`~`T-004`;Phase 1 的 `T-101`、`T-102`。
|
||||
- 正在进行:无。
|
||||
- 下一个可领取任务:按路线图落成并领取 `T-102 ZIP 安全解压原型`。
|
||||
- 下一个可领取任务:按路线图落成并领取 `T-103 staging/backup 原子切换与回滚原型`。
|
||||
|
||||
## 当前可运行内容
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
id: T-102
|
||||
title: ZIP 软件包安全解压原型
|
||||
phase: 1
|
||||
deps: [T-002]
|
||||
status: DONE
|
||||
created: 2026-07-16
|
||||
issue: null
|
||||
context_ref: 0d6ed05d7e69f4a8e2a20e93051e1fe48a868940
|
||||
claim_branch: null
|
||||
work_branch: agent/codex/T-102
|
||||
write_paths:
|
||||
- docs/tasks/T-102.md
|
||||
- core/installer/
|
||||
- testdata/zip/
|
||||
- docs/api.md
|
||||
- docs/04-architecture.md
|
||||
- docs/current-state.md
|
||||
---
|
||||
|
||||
## 问题 / 背景
|
||||
|
||||
软件包最终会把远端 ZIP 内容写入 staging 并切换为可执行程序。仅依赖 `archive/zip` 默认行为无法防止路径穿越、Windows 盘符/ADS、符号链接、重复覆盖和 zip bomb,必须在写磁盘前完整预检。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 在 `core/installer` 建立 `Extractor`,调用者显式提供条目数、总解压体积和压缩比限制。
|
||||
2. 两阶段处理:先验证整个中央目录和 entrypoint,全部通过后才创建新的 staging 目录并解压 `payload/` 内容。
|
||||
3. 拒绝绝对路径、盘符/冒号、反斜杠、空/NUL/非规范路径、`..`、大小写折叠重复路径、符号链接、特殊文件、加密条目和协议外顶层条目。
|
||||
4. 对每个条目及全包执行压缩比检查,实际复制时再次用剩余总量限制读取,失败清理本次创建的 staging。
|
||||
5. entrypoint 必须是 payload 内安全相对路径,并对应 ZIP 中的普通文件。
|
||||
6. 使用表驱动测试在运行时生成攻击 ZIP;`testdata/zip` 记录样例策略与限制结论。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 合法包只把 `payload/` 内容解压到新 staging,不复制 `app.json` / `files.json`。
|
||||
- 绝对路径、`../`、反斜杠穿越、盘符/ADS、符号链接、特殊文件和重复路径全部拒绝。
|
||||
- 条目数、总解压体积、单条/总体压缩比超限全部拒绝。
|
||||
- entrypoint 绝对/穿越/payload 外逃或不存在全部拒绝。
|
||||
- 任一预检/复制失败不留下可被误用的 staging 目录。
|
||||
- Go 1.20 core vet/test 和完整双目标闸门通过。
|
||||
|
||||
## 边界(不改什么)
|
||||
|
||||
- 不实现 SHA-256、Catalog/package 身份比对、app.json/files.json Schema(T-302/T-201)。
|
||||
- 不执行任何包内脚本,不处理 prerequisites。
|
||||
- 不切换 current/backup(T-103)。
|
||||
- 默认限制是 Phase 1 原型值,T-302 正式整合时按真实包规模复核。
|
||||
|
||||
## 协作约束
|
||||
|
||||
未启用 Gitea;本任务在 `agent/codex/T-102` 分支串行执行。Extractor 文档明确要求调用者只传入已完成签名与 SHA-256 校验的 ZIP。
|
||||
|
||||
## 执行记录
|
||||
|
||||
- 2026-07-16:在 `core/installer` 建立 Limits/Extractor,采用完整预检后再创建 staging 的两阶段流程;只解压 `payload/`,不复制根部元数据。
|
||||
- 2026-07-16:路径规则拒绝无效 UTF-8、NUL、绝对/UNC、盘符/冒号/ADS、反斜杠、非规范路径与 `..`;大小写折叠后重复路径也拒绝,避免 Windows 覆盖歧义。
|
||||
- 2026-07-16:拒绝符号链接、特殊文件、加密条目、协议外顶层文件;要求 app.json 存在且 entrypoint 是 payload 内精确匹配的普通文件。
|
||||
- 2026-07-16:原型默认限制为 10,000 条目、4 GiB 总展开、单条/总体 200:1 压缩比;实际复制再次按剩余额度限流并核对 header 展开大小。
|
||||
- 2026-07-16:任一复制、CRC 或关闭错误会删除本次新建 staging;已有 destination 直接拒绝,不覆盖未知内容。
|
||||
- 2026-07-16:攻击 ZIP 由表驱动测试运行时生成,策略记录于 `testdata/zip/README.md`;标准库会先解析中央目录再暴露条目列表,如需抵御超大中央目录的预解析内存压力,T-302 应增加 ZIP 文件/中央目录预扫描限制。
|
||||
- 定向测试通过:合法 payload、绝对/盘符/ADS/`../`/反斜杠、加密、symlink、特殊文件、重复路径、协议外文件、条目数、总展开、压缩比、entrypoint 外逃/缺失、已有 staging 和 CRC 损坏清理。
|
||||
- 验证通过:Go 1.20.14 core vet/test。
|
||||
- 验证通过:`./scripts/verify_phase0.ps1`,包含 modern/win7 双目标构建与治理检查。
|
||||
Reference in New Issue
Block a user