Skip to content

fix: 修复缺少站点访问权限时跨域请求异常的问题#1477

Merged
CodFrm merged 6 commits into
mainfrom
fix/site-access-grant/001
Jun 5, 2026
Merged

fix: 修复缺少站点访问权限时跨域请求异常的问题#1477
CodFrm merged 6 commits into
mainfrom
fix/site-access-grant/001

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented May 28, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

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

Description / 描述

Close #1476

修复在浏览器未授予 ScriptCat 对目标站点的访问权限时,脚本发起跨域请求可能出现非预期错误的问题。

本次改动会在处理 GM.xmlHttpRequest / 跨域请求权限确认时,先检查扩展是否已拥有目标 origin 的站点访问权限。如果尚未授权,则在确认页面引导用户通过浏览器权限弹窗授予对应站点访问权限,授权成功后再继续执行请求;如果用户拒绝授权,则本次请求会被拒绝。

主要改动

  • 在跨域请求权限校验中增加对 chrome.permissions.contains 的检查。
  • 当缺少目标站点访问权限时,返回新的 extension-site-access 确认类型。
  • 在确认页面中调用 chrome.permissions.request,通过用户手势请求站点访问权限。
  • 针对站点访问权限确认场景,简化确认页面按钮,只显示“请求权限”。
  • 为多语言文件补充“ScriptCat 需要站点访问权限”相关文案。
  • 保留原有 CORS / @connect 权限判断逻辑,并在已允许 CORS 但缺少站点访问权限时继续请求浏览器站点权限。

测试

已验证以下场景:

  • 未授予站点访问权限时,会弹出 ScriptCat 的站点访问权限确认页面。
  • 用户点击请求权限后,会触发浏览器的站点访问权限授权弹窗。
  • 用户拒绝授权时,请求会被正确拒绝。
  • 用户允许授权后,请求可以继续执行。
  • 原有 CORS 权限确认流程仍可正常工作。

Screenshots / 截图

Screenshot 2026-05-29 at 0 45 34 Screenshot 2026-05-29 at 0 45 39

DENY

Screenshot 2026-05-29 at 0 45 48

ALLOW

Screenshot 2026-05-29 at 0 46 01 Screenshot 2026-05-29 at 0 46 10

m501a.user.js
m501b.user.js
server.zip

@cyfung1031 cyfung1031 changed the title fix site-access-grant fix: 修复缺少站点访问权限时跨域请求异常的问题 May 28, 2026
@cyfung1031 cyfung1031 requested a review from CodFrm May 28, 2026 16:14
@CodFrm CodFrm requested a review from Copilot May 28, 2026 16:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 旨在修复当浏览器未授予扩展对目标站点的“站点访问权限”时,脚本发起 GM.xmlHttpRequest / GM_xmlhttpRequest 跨域请求可能出现非预期异常的问题。整体思路是在原有 @connect / CORS 确认链路之外,增加对扩展“站点访问权限(Site access)”的检测与引导授权,从而避免在权限被浏览器侧拦截时产生不可控错误。

Changes:

  • 在 Service Worker 侧为 XHR 跨域请求增加 chrome.permissions.contains 检测,并在缺少站点访问权限时返回新的确认类型 extension-site-access
  • 在确认页面中增加 chrome.permissions.request({ origins }) 的用户手势授权流程,并为 extension-site-access 场景简化按钮 UI
  • 为多语言资源补充“需要站点访问权限”的标题/描述/内容文案

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/pages/confirm/App.tsx 确认页新增站点访问权限请求逻辑,并对 extension-site-access 场景简化按钮
src/app/service/service_worker/permission_verify.ts 扩展 ConfirmParam,增加 extensionSiteAccessOrigins 字段用于确认页触发权限申请
src/app/service/service_worker/gm_api/gm_api.ts XHR 权限确认前新增站点访问权限检测,必要时返回 extension-site-access 确认
src/locales/zh-TW/translation.json 新增站点访问权限相关文案(繁中)
src/locales/zh-CN/translation.json 新增站点访问权限相关文案(简中)
src/locales/vi-VN/translation.json 新增站点访问权限相关文案(越南语)
src/locales/ru-RU/translation.json 新增站点访问权限相关文案(俄语)
src/locales/ja-JP/translation.json 新增站点访问权限相关文案(日语)
src/locales/en-US/translation.json 新增站点访问权限相关文案(英语)
src/locales/de-DE/translation.json 新增站点访问权限相关文案(德语)

Comment thread src/pages/confirm/App.tsx
Comment on lines +48 to +62
if (allow && confirm?.extensionSiteAccessOrigins?.length) {
const granted = await chrome.permissions.request({
origins: confirm.extensionSiteAccessOrigins,
});
if (!granted) {
await permissionClient
.confirm(uuid, {
allow: false,
type,
})
.catch(() => {});
window.close();
return;
}
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only 1

Comment on lines +810 to +817
const originPattern = `${url.origin}/*`;
let hasOriginPermission = false;
try {
hasOriginPermission = await chrome.permissions.contains({ origins: [originPattern] });
} catch (e) {
console.warn(e);
}
const extensionSiteAccessOrigins = hasOriginPermission ? undefined : [originPattern];

@cyfung1031 cyfung1031 May 28, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 要包括 port
  2. file:/// 暂不理会 36ad338
  3. fixed about:blank, data:text/html,... in 408f0e3

@cyfung1031

Copy link
Copy Markdown
Collaborator Author

@CodFrm 你知不知道有什么情况才会有由「所有网络」变成「特定网站」的情况吗? 脚本安装页弹出也是用 DNR,如果是「特定网站」的情况下就会失效...

@CodFrm

CodFrm commented May 31, 2026

Copy link
Copy Markdown
Member

@CodFrm 你知不知道有什么情况才会有由「所有网络」变成「特定网站」的情况吗? 脚本安装页弹出也是用 DNR,如果是「特定网站」的情况下就会失效...

一般是用户自己设定吧,其它情况我也不清楚了

@CodFrm CodFrm merged commit fdee1ce into main Jun 5, 2026
3 of 4 checks passed
@CodFrm CodFrm deleted the fix/site-access-grant/001 branch June 5, 2026 07:10
CodFrm added a commit to cyfung1031/scriptcat that referenced this pull request Jun 11, 2026
- gm-api.spec.ts: scriptscat#1477 迁移到本地 mock server 时漏改 unwrap 测试,仍引用已删除的 TARGET_URL 导致 ReferenceError。改用 cspOrigin,并把 unwrap_e2e_test token 接入 patchTargetMatchCode

- concurrency-control.test.ts: 操作全局计时器/console 的 3 个用例从 it.concurrent 改回顺序 it,避免并发互相干扰偶现失败
CodFrm added a commit that referenced this pull request Jun 11, 2026
* x

* 处理并行fetch问题

* 修复 src/app/service/service_worker/runtime.ts

* 本地资源代码更新逻辑修正

* Update script.ts

* fix

* getResourceByType -> getResourceByTypes

* 加入注意

* getScriptResources -> getScriptResourceValue

* 代码调整

* `mdValue.startsWith("file:///")` -> `resourcePath.startsWith("file:///")`

* 代码调整

* 代码调整

* 代码调整

* `loadByUrl` -> `createResourceByUrlFetch`

* 简化 updateResource signature

* 简化 createResourceByUrlFetch

* lint

* `updateResourceByType` -> `updateResourceByTypes`

* 加注釋

* 代码优化 - 资源更新条件修改

* 注釋

* lint

* 调整代码 - updateResource & createResourceByUrlFetch

* 统一 try catch 在 updateResource 里进行

* 修正 Semaphore 相关代码

* 把并行控制的代码移动至 concurrency-control.ts

* Update src/app/service/service_worker/resource.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/app/service/service_worker/utils.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* ♻️ 优化资源加载代码:提取魔法数字、清理疑问注释、添加并发控制单元测试

- 提取魔法数字为命名常量(MAX_CONCURRENT_FETCHES, FETCH_DELAY, FETCH_SEMAPHORE_TIMEOUT, RESOURCE_CACHE_TTL)
- 清理疑问注释,改为明确的设计决策说明
- 为 Semaphore 和 withTimeoutNotify 添加单元测试

* 改回注释

* 按AI指示语意更新

* 根据AI意见修正

* fix

* 修正 Semaphore

* fix unit test

* unit test fix

* Commits 整合

* ✅ add failing tests for resource concurrency regressions

* 🐛 修复资源更新缓存与并发控制

* 🐛 修复资源 TTL 命中时未登记 link 导致共享资源被误删

updateResourceByTypes 在 24 小时 TTL 命中时直接 return,不会把当前脚本 uuid 写入 resource.link。多个脚本复用同一 URL 时,删除其中一个脚本会把仍被其它脚本使用的资源一并删除。

TTL 命中时也补登记 link(只更新 link 字段,避开 getResourceModel 对 SRI 校验失败时改写 content 的副作用)。

* ✅ 修复 unwrap e2e 测试与并发测试的全局状态污染

- gm-api.spec.ts: #1477 迁移到本地 mock server 时漏改 unwrap 测试,仍引用已删除的 TARGET_URL 导致 ReferenceError。改用 cspOrigin,并把 unwrap_e2e_test token 接入 patchTargetMatchCode

- concurrency-control.test.ts: 操作全局计时器/console 的 3 个用例从 it.concurrent 改回顺序 it,避免并发互相干扰偶现失败

---------

Co-authored-by: 王一之 <yz@ggnb.top>
Co-authored-by: wangyizhi <i@xloli.top>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CodFrm added a commit that referenced this pull request Jun 12, 2026
为 v1.4.0-beta.3 → beta.4 的核心改动补充 Playwright E2E(复用现有两阶段
userScripts fixture,并新增本地 mock server + host-resolver 域名映射,全程不依赖外网):

- resource-update: @require/@resource 注入与读取、24h TTL 同 URL 去重、
  拉取失败优雅降级、多 require 并发全部加载 (#1193)
- gm-xhr-site-access: 跨域 @connect 放行、x-sc-request-marker 经 DNR 剥离、
  非 @connect 域名拒绝 (#1477, mv3_utils)
- background-script: @background 脚本经 Chrome offscreen 执行并具备 DOM 环境 (#1457)
- user-config-yaml: 含 __proto__ 的恶意 @userconfig 被拒、原型链未污染 (#1494)
- backup-zip: 备份导出/导入 zip 往返(JSZipp generateAsync/loadAsync)(#1479)
- server-fixtures: 共享 fixture + mock server
CodFrm added a commit that referenced this pull request Jun 12, 2026
为 v1.4.0-beta.3 → beta.4 的核心改动补充 Playwright E2E(复用现有两阶段 userScripts fixture,并新增本地 mock server + host-resolver 域名映射,全程不依赖外网):

- resource-update: @require/@resource 注入与读取、24h TTL 同 URL 去重、拉取失败优雅降级、多 require 并发全部加载 (#1193)

- gm-xhr-site-access: 跨域 @connect 放行、x-sc-request-marker 经 DNR 剥离、非 @connect 域名拒绝 (#1477, mv3_utils)

- background-script: @background 脚本经 Chrome offscreen 执行,具备 DOM 环境,并通过脚本内 GM 值读写闭环 + mock server probe 做稳定断言 (#1457)

- user-config-yaml: 含 __proto__ 的恶意 @userconfig 被拒、原型链未污染 (#1494)

- backup-zip: 备份导出/导入 zip 往返(JSZipp generateAsync/loadAsync)(#1479)

- e2e waits: 移除固定 sleep/忙等,改为条件等待;并升级 workflow action runtime 版本

- server-fixtures: 共享 fixture + mock server
CodFrm added a commit that referenced this pull request Jun 12, 2026
为 v1.4.0-beta.3 → beta.4 的核心改动补充 Playwright E2E(复用现有两阶段 userScripts fixture,并新增本地 mock server + host-resolver 域名映射,全程不依赖外网):

- resource-update: @require/@resource 注入与读取、24h TTL 同 URL 去重、拉取失败优雅降级、多 require 并发全部加载 (#1193)

- gm-xhr-site-access: 跨域 @connect 放行、x-sc-request-marker 经 DNR 剥离、非 @connect 域名拒绝 (#1477, mv3_utils)

- background-script: @background 脚本经 Chrome offscreen 执行,具备 DOM 环境,并通过脚本内 GM 值读写闭环 + mock server probe 做稳定断言 (#1457)

- user-config-yaml: 含 __proto__ 的恶意 @userconfig 被拒、原型链未污染 (#1494)

- backup-zip: 备份导出/导入 zip 往返(JSZipp generateAsync/loadAsync)(#1479)

- e2e waits: 移除固定 sleep/忙等,改为条件等待;并升级 workflow action runtime 版本

- server-fixtures: 共享 fixture + mock server
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P0 🚑 需要紧急处理的内容

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] 缺少扩展站点访问权限时 GM_xmlhttpRequest 跨域请求会出现非预期错误

3 participants