[REQ-128][CODE] fetchPackageAsset 补 timeout 与终态 URL 的 HTTPS/userinfo 复查 - #820
Merged
Conversation
added 2 commits
August 3, 2026 05:07
宿主取回资产这一跳此前只有 redirect:"error" 与字节双查,与 payload 那条路 (package-installability.ts:37/539/543/546-550)差两件: ① 无期限 —— 服务端保持连接不发 EOF,await fetch 就永不落地,整个 admission 停在这里(没有超时、没有拒绝、没有错误),用户看到安装按钮永远转圈; ② 不复查终态 URL —— response.url 是运行时给出的终态地址,payload 路径已在读它。 两条补齐后逐条对称。抛出物被调用点吞成空字节 ⇒ 撞上 bytes/sha256 双查 ⇒ 整包具名拒绝。 判据(R1 审计 F10):真 createPackageAdmissionCoordinator、不传 deps.fetchAsset、 也不传 installability.fetchPayload,只替换 globalThis.fetch —— 注入态下把这两道 guard 整段删掉,现有 package 测试照样全绿。 Fixes #808 Refs #699
这 5 条跑在整包 `bun test src` 里,删掉整个文件是 3799→3794,远高于地板 3000 ⇒ 静默全绿,而两道 guard 一起消失。整包地板管灾难,点名下界才管单文件消失。 Refs #808
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #808
Refs #699
大白话
宿主从 catalog 下载扩展包资产的那一跳,今天缺两个保护:
await fetch(...)就永不落地。整个 admission 停在这里,没有超时、没有拒绝、没有错误。用户看到的是安装按钮永远转圈。response.url是运行时给出的最终地址;payload 那条路已经在读它并校验 HTTPS/userinfo,资产这条路没有。两条补齐后,与 payload 路径(
package-installability.ts:37/539/543/546-550)逐条对称。这正是基线 §5 第 2 类「catalog → 宿主」那一行要补的东西。范围
只有
fetchPackageAsset(packages/ui-mac/src/main/package-admission.ts)一个函数 + 一个模块常量。与载荷种类无关:凡是内容寻址资产都走这个函数。票面原本含第 ① 半(
assetRef取值条件接受 script 资产形状),那半已由#809顺带做掉(package-admission.ts:529-538,随alpha@5ef04016落地),本 PR 一行未动。判据(R1 审计 F10,假闸形态⑤/⑧)
admission 取资产时优先用注入的 helper:
(deps.fetchAsset ?? fetchPackageAsset)(assetRef),而现有 package 测试大量注入它(package-update.test.ts五处、package-admission.parity.test.ts一处)⇒ 注入态下把这两道 guard 整段删掉,那些测试照样全绿。所以新增的
packages/ui-mac/src/main/package-asset-fetch.test.ts:createPackageAdmissionCoordinator;deps.fetchAsset,也不传installability.fetchPayload(两条取回都落到生产下载器);globalThis.fetch。五条用例 = 三条 mutation + 两条控制:
signal.aborted === true+ 拒绝理由恰是资产完整性那条 + 零事务调用)setTimeout(...controller.abort())每条负例都同时断言「那个资产 URL 真的被请求过」+「它前面那个资产正常取回了」+「它后面那个资产没被请求」+「零事务调用」——只断
ok === false会被「根本没下载就拒」的实现满足。绕过实施记录(本机实测,原始输出)
mutation ① —— 把
setTimeout(() => controller.abort(), ASSET_TIMEOUT_MS)改成 no-op、并从 fetch init 里摘掉signal:正是「挂死」而不是「拒绝」的指纹。用例显式声明 30s 超时(bun 默认 5s 会在生产 8s 期限之前杀掉用例 ⇒ 量到的是「跑得太久」不是「没有期限」,判据完全不同)。
mutation ② —— 删掉终态 URL 复查那 5 行:
收到的对象是
"stage": "authorize"的完整授权预览 —— 即放行,不是别的什么理由的拒绝。两次实验都在
git status干净(改动已 commit)之后做,还原后git diff为空、git log未动。闸门登记
新文件登记进
scripts/gate-files.tsv(下界 5,不留余量)。理由:这 5 条跑在整包bun test src里,删掉整个文件是 3799→3794,远高于地板 3000 ⇒ 静默全绿,而两道 guard 一起消失。本地门(真实输出)
bash scripts/alpha-check.sh—— 12/12 步全绿:与 base(
alpha@5ef04016)的差:零回归。
诚实边界
终态 URL 复查是纵深保护,与 payload 侧同因同形 —— 不是「今天已知有一条路能绕过
redirect:"error"」。生产里redirect:"error"会在重定向时直接拒,所以真实终态 URL 恒等于请求 URL;这道复查管的是「我们这份 fetch 实现之外」的情形。代码注释里如实写成这样,没有夸大成一个可复现的攻击。