You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Searched existing issues for @match, unsupported/invalid schemes, and userScripts registration failures; no duplicate for this case was found.
Confirmed against the current main source (d6cc48ba99f8a8ac7d4ad236f2d294fad99e0c79) that the invalid scheme is still accepted into the registration match list.
This is a ScriptCat URL-matching / registration bug, not a problem specific to one third-party userscript.
Description
A userscript with multiple @match entries stops running entirely if one entry uses a scheme that Chrome does not support as a match-pattern scheme.
Expected behavior: the unsupported/invalid @match entry should be rejected or ignored for browser registration, while the valid https://*/* and http://*/* entries continue to register and run.
Actual behavior: ScriptCat accepts all three entries into one RegisteredUserScript.matches array. Chrome validates that array when chrome.userScripts.register() / .update() is called; the unsupported scheme makes that script registration fail, so the valid patterns never become active either.
The key point is that Manifest V3 itself is not the root cause. MV3/chrome.userScripts is the stricter API boundary that exposes the problem. The root cause is that ScriptCat does not filter or reject match patterns that are invalid for the browser-native match-pattern API before passing them to chrome.userScripts.
Steps to Reproduce
Create a page userscript with the following metadata:
Open or reload any normal HTTPS page, for example https://example.com/.
Observe that the script does not execute.
Remove only // @match notsupported://*/*, save/re-enable as needed, then reload the same page.
The script runs from the remaining valid https://*/* / http://*/* patterns.
ScriptCat Version
Current main reproduced/confirmed at:
d6cc48ba99f8a8ac7d4ad236f2d294fad99e0c79
OS / Browser and Version
Chromium/Chrome MV3 path using chrome.userScripts.
The exact local Chrome version is not material to the source-level reproduction; the failure is caused by passing an unsupported scheme into the browser's match-pattern API. The original UI reproduction was on a Chromium-based browser.
src/app/service/service_worker/runtime.ts registers/updates that one record through chrome.userScripts.register([registerScript]) / .update([registerScript]). A registration error is logged, but there is no per-pattern recovery.
The third entry is not a valid Chrome extension match-pattern scheme. Chrome's documented match-pattern schemes are http, https, file, and * (the wildcard for HTTP/HTTPS):
This behavior became a regression when ScriptCat changed the page-script registration architecture, but the architectural migration is not itself the defect.
Related failure-class evidence:3f57e8f5000da299e959899ec9dc785c239e2c11 fixed issue [BUG]特殊路径无法加载 #390 by falling back from batch registration to one-script-at-a-time registration after a bad match pattern caused userScripts.register() to fail.
That isolates failures between scripts.
It does not isolate invalid @match entries within one script.
Later matcher rewrite:5b01c10859b80890456a44a66d78204b42040870 / PR 重写UrlMatch #637 rewrote URL matching, but the semantic gap remained: arbitrary lowercase schemes still pass the ScriptCat parser even when they are not valid native match-pattern schemes.
The registration-bound URL parser validates the shape of a scheme (lowercase letters / wildcard), but does not validate whether the scheme is actually supported by the browser's native match-pattern API.
As a result, an unsupported @match is treated as a native MATCH_INCLUDE and forwarded unchanged into chrome.userScripts. Because all native matches for one userscript are registered together, one invalid entry can prevent the whole userscript registration from succeeding.
Suggested direction
At a high level, validate/filter native registration patterns at the ScriptCat → browser API boundary so an unsupported @match cannot invalidate otherwise-valid patterns from the same userscript.
The fix should preserve the valid rules, add focused regression coverage for mixed valid + invalid @match entries, and make registration failures diagnosable. Detailed implementation design can be handled in the follow-up PR.
Pre-check
@match, unsupported/invalid schemes, anduserScriptsregistration failures; no duplicate for this case was found.mainsource (d6cc48ba99f8a8ac7d4ad236f2d294fad99e0c79) that the invalid scheme is still accepted into the registration match list.Description
A userscript with multiple
@matchentries stops running entirely if one entry uses a scheme that Chrome does not support as a match-pattern scheme.Example:
Expected behavior: the unsupported/invalid
@matchentry should be rejected or ignored for browser registration, while the validhttps://*/*andhttp://*/*entries continue to register and run.Actual behavior: ScriptCat accepts all three entries into one
RegisteredUserScript.matchesarray. Chrome validates that array whenchrome.userScripts.register()/.update()is called; the unsupported scheme makes that script registration fail, so the valid patterns never become active either.The key point is that Manifest V3 itself is not the root cause. MV3/
chrome.userScriptsis the stricter API boundary that exposes the problem. The root cause is that ScriptCat does not filter or reject match patterns that are invalid for the browser-native match-pattern API before passing them tochrome.userScripts.Steps to Reproduce
Create a page userscript with the following metadata:
Enable the script.
Open or reload any normal HTTPS page, for example
https://example.com/.Observe that the script does not execute.
Remove only
// @match notsupported://*/*, save/re-enable as needed, then reload the same page.The script runs from the remaining valid
https://*/*/http://*/*patterns.ScriptCat Version
Current
mainreproduced/confirmed at:d6cc48ba99f8a8ac7d4ad236f2d294fad99e0c79OS / Browser and Version
Chromium/Chrome MV3 path using
chrome.userScripts.The exact local Chrome version is not material to the source-level reproduction; the failure is caused by passing an unsupported scheme into the browser's match-pattern API. The original UI reproduction was on a Chromium-based browser.
Related Script / Logs / Screenshots
Current code path
src/pkg/utils/url_matcher.tsaccepts arbitrary lowercase alphabetic schemes.checkUrlMatch()currently checks the scheme with:/^(\*|[-a-z]+)$/and
extractUrlPatterns()similarly accepts arbitrary[-a-z]+schemes for@match.Source:
https://github.com/scriptscat/scriptcat/blob/d6cc48ba99f8a8ac7d4ad236f2d294fad99e0c79/src/pkg/utils/url_matcher.ts
getApiMatchesAndGlobs()collects acceptedMATCH_INCLUDEentries into the final nativematcheslist without filtering unsupported browser schemes.src/app/service/service_worker/utils.tsplaces that list directly into a singlechrome.userScripts.RegisteredUserScript.matchesarray.Source:
https://github.com/scriptscat/scriptcat/blob/d6cc48ba99f8a8ac7d4ad236f2d294fad99e0c79/src/app/service/service_worker/utils.ts
src/app/service/service_worker/runtime.tsregisters/updates that one record throughchrome.userScripts.register([registerScript])/.update([registerScript]). A registration error is logged, but there is no per-pattern recovery.Source:
https://github.com/scriptscat/scriptcat/blob/d6cc48ba99f8a8ac7d4ad236f2d294fad99e0c79/src/app/service/service_worker/runtime.ts
For the reproduction metadata, ScriptCat currently produces a native match list equivalent to:
The third entry is not a valid Chrome extension match-pattern scheme. Chrome's documented match-pattern schemes are
http,https,file, and*(the wildcard for HTTP/HTTPS):https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns
Regression history / evidence
This behavior became a regression when ScriptCat changed the page-script registration architecture, but the architectural migration is not itself the defect.
Known-good pre-MV3 reference:
ad5a7116c9d54b4e4a4ab53420d0e1d185612f98chrome.tabs.executeScript(...).First bad implementation commit:
fcb4cc48afcb12106eec8d39a5d902504e2553fc(♻️ 重构代码,升级为manifest v3, 2025-04-23)chrome.userScriptsregistration path.fcb4cc4
Landed on
main: PR ♻️ 重构代码,升级为manifest v3 #374 / merge commit9b283ef5f9ce12f3b71c5f49b6b246f1facfd167, 2025-05-13.♻️ 重构代码,升级为manifest v3 #374
Related failure-class evidence:
3f57e8f5000da299e959899ec9dc785c239e2c11fixed issue [BUG]特殊路径无法加载 #390 by falling back from batch registration to one-script-at-a-time registration after a bad match pattern causeduserScripts.register()to fail.@matchentries within one script.3f57e8f
[BUG]特殊路径无法加载 #390
Later matcher rewrite:
5b01c10859b80890456a44a66d78204b42040870/ PR 重写UrlMatch #637 rewrote URL matching, but the semantic gap remained: arbitrary lowercase schemes still pass the ScriptCat parser even when they are not valid native match-pattern schemes.重写UrlMatch #637
Root cause
The registration-bound URL parser validates the shape of a scheme (lowercase letters / wildcard), but does not validate whether the scheme is actually supported by the browser's native match-pattern API.
As a result, an unsupported
@matchis treated as a nativeMATCH_INCLUDEand forwarded unchanged intochrome.userScripts. Because all native matches for one userscript are registered together, one invalid entry can prevent the whole userscript registration from succeeding.Suggested direction
At a high level, validate/filter native registration patterns at the ScriptCat → browser API boundary so an unsupported
@matchcannot invalidate otherwise-valid patterns from the same userscript.The fix should preserve the valid rules, add focused regression coverage for mixed valid + invalid
@matchentries, and make registration failures diagnosable. Detailed implementation design can be handled in the follow-up PR.