Skip to content

🐛 修正脚本资源分类与页面资源权限边界 - #1686

Open
cyfung1031 wants to merge 16 commits into
mainfrom
codex/add-performance-verification-tests
Open

🐛 修正脚本资源分类与页面资源权限边界#1686
cyfung1031 wants to merge 16 commits into
mainfrom
codex/add-performance-verification-tests

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

N/A — 本 PR 未关联需要自动关闭的 issue;主要跟进 PR review 中确认的资源边界问题。

Description / 描述

背景

ResourceService 原先会把 @require@require-css@resource 合并到同一个 string-keyed map,再沿页面执行链路继续传递。这样会带来三个问题:

  1. 已经编译进脚本代码的 @require 仍可能被重复带入页面 payload;
  2. @resource 没有按实际可用的 GM Resource API grant 做边界过滤;
  3. 不同资源类别使用相同 key 时,合并 map 会丢失类别来源,导致 consumer 可能读取错误类别的内容。

后续 review 还确认了两个兼容性缺口:页面 resource gate 与 createContext()GM. / GM_ grant 转换规则曾经各自维护,可能静默丢弃合法 @resource;同时 GM.getResourceURL 虽已出现在 ScriptCat 的公开类型中,runtime API 注册并未完整覆盖该大小写形式。

本次改动

  • 新增共享的 parseResourceDeclaration(),让资源读取和安装/更新路径使用同一套 @resource <name> <url> 解析规则;非法声明不会进入资源下载流程。
  • 在 Service Worker 内保留 requirerequire-cssresource 三个独立 map,并让编译、页面缓存、本地 file:/// 刷新及各 consumer 优先使用类别来源。
  • 页面边界只保留真实 page-side consumer 需要的数据:
    • @require 已编译进代码,不再作为页面 resource payload 转发;
    • @require-css 单独放入 requireCssResource
    • @resource 只在脚本具有有效 Resource API grant 时转发声明过的名称。
  • 抽出共享 getGrantCandidates(),由 createContext() 与 page resource gate 共用 GM.GM_ compatibility expansion,避免两套规则再次漂移。
  • Resource grant 行为覆盖以下六种既有/兼容写法:
    • GM_getResourceText
    • GM.getResourceText
    • GM_getResourceURL
    • GM.getResourceUrl
    • GM.getResourceURL
    • GM_getResourceUrl
  • 补上 GM.getResourceURL runtime API,与公开类型定义保持一致。
  • GM Resource API 在存在 resourceByType 时只读取 resourceByType.resource;仅对没有分类表的旧 payload 回退到 legacy resource,避免 background/scheduled script 把同名 @require 当作 @resource 读取。
  • 保留 script_executorrequireCssResource ?? resource 兼容路径,用于旧的已注册 userscript payload。

测试与回归覆盖

新增/调整的测试覆盖:

  • 六种 Resource API grant 从 trimScriptInfo()createContext() 再到真实 GM API 调用的跨边界行为;
  • 普通 @grant none 与 context-menu 的既有 grant 语义;
  • @require / @require-css / @resource 同 key 时的类别隔离;
  • @require 编译顺序及页面 payload 不重复携带;
  • @require-css 声明顺序与 category-specific CSS 选择;
  • malformed @resource 不创建资源、也不触发安装下载;
  • GM Resource API category source 与 legacy payload fallback;
  • page-load resource cache 保留分类来源并维持 legacy merged view;
  • 本地资源刷新继续更新对应类别。

与本问题无关的 sandbox isolation / value-update routing 验证已从本 PR final diff 移除,避免扩大审查范围。

实现考虑与兼容性

ScriptRunResource.resource 的 merged map 目前仍作为兼容形状保留,但新的核心 consumer 已改用类别来源。完全移除 merged internal model 会涉及 background/sandbox、注册脚本 payload 与跨版本兼容,留待后续独立 refactor,不在本 bug-fix PR 扩大范围。

本 PR 不宣称量化的 heap 或 runtime 性能提升。当前可以直接由数据流验证的是:页面边界不再携带已编译的 @require,并且未获得 Resource API 能力的脚本不会收到对应 @resource payload。定量内存/性能比较留给后续 profiling。

建议审查重点

  1. getGrantCandidates() 是否与 createContext() 的既有 grant compatibility 语义一致;
  2. 六种 Resource API grant 是否都能在页面 trimming 后实际调用对应 API;
  3. resourceByType 是否在 page cache、local refresh、background/sandbox 与页面 consumer 间保持正确类别;
  4. legacy resource / CSS fallback 是否只承担兼容职责,没有重新成为新路径的权威 source;
  5. 同 key 跨 require / require-css / resource 时,各 consumer 是否读取正确类别。

验证

Final diff 绑定:

  • Base: a466b22ef78fa983348f298b1737a4ad24cec196
  • Head: 2a9a55e633e83061ea31e5fc111d059cac3c42e3
  • Changed files: 16

当前 head 的 GitHub checks:

  • GitHub Actions test workflow — success
  • Lint — success
  • Unit test shards 1/2、2/2 — success
  • E2E shards 1/4–4/4 — success
  • Final test/coverage aggregation — success
  • License Compliance — success
  • codecov/projectsuccess, 72.08% (+0.01%) compared with base a466b22

早期 head 曾做过额外本地与 browser verification,但由于之后仍有 grant/API/test commits,本描述不把那些旧 revision 的结果作为 final-head acceptance evidence;当前 readiness 以以上绑定到 2a9a55e 的远端 checks 与 final diff 为准。

Screenshots / 截图

N/A — 非视觉改动。

@cyfung1031 cyfung1031 changed the title ✅ 增加脚本执行路径验证测试 ✅ 修正资源分类边界并降低页面脚本资源开销 Aug 22, 2026
@cyfung1031
cyfung1031 marked this pull request as ready for review August 22, 2026 01:32
@cyfung1031

cyfung1031 commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator Author

结论:发现一个 P2,建议 Request changes,置信度高。

[P2] 非法 @resource 声明仍可能触发安装下载

位置:

触发值:

" https://example.com/payload"

新解析器:

value.split(/\s+/)
// ["", "https://example.com/payload"]

会因首项为空而拒绝。但安装路径中的旧逻辑:

const split = u.split(/\s+/);
if (split.length === 2) {
  url = split[1];
}

会把第二项当作 URL,继续进入 parseUrlSRIupdateResource,可能发起网络请求并持久化资源。

因此,PR 声称的“非法声明不会创建资源或触发下载”并未覆盖安装路径。

建议:

  • updateResourceByTypes 复用 parseResourceDeclaration
  • 增加直接覆盖安装路径的回归测试。

结论:发现 1 个 Medium finding,建议修改后合并。
证据路径:

  1. script.ts (line 897) 同时生成 resourceByType 和合并后的 resource。
  2. 后台/定时脚本经 offscreen/script.ts (line 56) 送入 Sandbox。
  3. gm_api.ts (line 1559) 仍读取 scriptRes.resource。
  4. 因此,声明 lib.js 并授予 GM_getResourceText 的后台脚本,可以用该 URL 读取 @require 内容,即使没有对应的 @resource
    建议修复:
  • GM Resource API 存在 resourceByType 时只读取 resourceByType.resource。
  • 仅对旧格式、没有分类表的 payload 回退到 resource。
  • 增加后台脚本和定时脚本回归测试。

Copy link
Copy Markdown
Collaborator Author

已针对本 PR 关联评论中的两个问题完成修复,并推送到当前 PR head 762795d9

修复内容:

  • 2619e4d1:先加入回归测试,确认父版本会下载前导空格等非法 @resource,且 GM Resource API 会把同名 @require 内容当成资源返回。
  • c79d8509:安装资源时复用 parseResourceDeclaration;解析失败时不会调用 updateResource 或发起 fetch。
  • 762795d9GM_getResourceText/URL 及异步 API 优先读取 resourceByType.resource,仅在没有分类表的旧 payload 中回退到合并的 resource,避免后台/定时脚本通过 @require 泄漏到 Resource API。

验证:

  • 每个 commit 均由独立只读 subagent 针对精确 SHA 验证并判定 ACCEPT。
  • 聚焦 Vitest:2 files / 59 tests passed。
  • 完整 lint、typecheck、i18n、issue-template checks passed。
  • build passed。
  • 相关 E2E:4/4 passed。
  • 完整 suite 首次并行运行有 5 个无关测试因短 timeout 失败(4222/4227 passed);单独重跑这 5 个文件后为 131/131 passed。
  • 当前 GitHub Actions checks 已启动,仍在进行中。

此修复沿用现有 parser 的声明形状语义,没有扩大 URL scheme 校验范围。

@cyfung1031
cyfung1031 marked this pull request as draft August 24, 2026 10:21
@cyfung1031

cyfung1031 commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator Author

改動較大。先人手測試一下再Ready

改動較大。先人手檢查一下代碼再Ready

@cyfung1031

This comment was marked as resolved.

@cyfung1031
cyfung1031 marked this pull request as ready for review September 8, 2026 20:21
@cyfung1031 cyfung1031 changed the title ✅ 修正资源分类边界并降低页面脚本资源开销 🐛 修正脚本资源分类与页面资源权限边界 Sep 8, 2026
@cyfung1031

Copy link
Copy Markdown
Collaborator Author

AI 修正了问题也审查了
我看了一下也觉得应该没问题
剩下的就是你看看跑起来有没有问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant