From 079feda71f8a322ee3782895be652f8764567f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Tue, 20 Oct 2026 14:14:15 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D=20native=20GM?= =?UTF-8?q?=5Fdownload=20=E4=B8=8B=E8=BD=BD=20data:=20URI=20=E6=97=B6?= =?UTF-8?q?=E8=AF=AF=E5=BC=B9=E8=B7=A8=E5=9F=9F=E6=9D=83=E9=99=90=E7=A1=AE?= =?UTF-8?q?=E8=AE=A4=20(#1635)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/service_worker/gm_api/gm_api.test.ts | 12 ++++++++++++ src/app/service/service_worker/gm_api/gm_api.ts | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/app/service/service_worker/gm_api/gm_api.test.ts b/src/app/service/service_worker/gm_api/gm_api.test.ts index 63b937997..f05fd6793 100644 --- a/src/app/service/service_worker/gm_api/gm_api.test.ts +++ b/src/app/service/service_worker/gm_api/gm_api.test.ts @@ -315,6 +315,18 @@ describe.concurrent("native GM_download 的 @connect 校验(verifyXhrConnect expect((ret as ConfirmParam).permission).toBe("cors"); }); + it.concurrent("native 下载 data: URI 不发起网络请求,无需 @connect 也直接放行 (#1635)", async () => { + const url = `data:text/csv;charset=utf-8,${encodeURIComponent("a,b,c\n1,2,3")}`; + expect(await downloadConfirm(makeReq({ url, downloadMode: "native" }), makeConnSender(), makeGmApi())).toBe(true); + expect( + await downloadConfirm( + makeReq({ url, downloadMode: "native", connect: ["example.com"] }), + makeConnSender(), + makeGmApi() + ) + ).toBe(true); + }); + it.concurrent("native 下载:域名命中 @connect 时放行", async () => { const req = makeReq({ url: "https://api.example.com/f.zip", downloadMode: "native", connect: ["example.com"] }); const ret = await downloadConfirm(req, makeConnSender(), makeGmApi()); diff --git a/src/app/service/service_worker/gm_api/gm_api.ts b/src/app/service/service_worker/gm_api/gm_api.ts index b2c91d5d0..a658951ed 100644 --- a/src/app/service/service_worker/gm_api/gm_api.ts +++ b/src/app/service/service_worker/gm_api/gm_api.ts @@ -1398,8 +1398,10 @@ export default class GMApi { @PermissionVerify.API({ // native 下载会发起真实跨域请求,需校验黑名单 / 站点访问 / @connect。 // 与 TM 不同(TM 的 @connect 只作用于 xhr/fetch),未列入 @connect 的域名改为弹窗询问由用户决定,而非直接拒绝。 + // data: URI 内容自带、不发起网络请求,没有可校验的域名,直接放行 (#1635) confirm: async (request, sender, gmApi) => { - if (request.params[0]?.downloadMode !== "native") { + const details = request.params[0]; + if (details?.downloadMode !== "native" || /^\s*data:/i.test(details.url)) { return true; } return gmApi.verifyXhrConnect(request, sender, true);