JustZix 的 JavaScript 规则现在在 Facebook、X 和 GitHub 上也能正常运行
那些过去让用户脚本 JS 失效的页面——Facebook、X、GitHub 以及许多采用严格 Content-Security-Policy 的网站——一直也是 JustZix 的瓶颈。在 3.2.0 版本中,我们改造了代码执行引擎,使其能够穿越这道屏障,而又不在网络其他部分做出任何妥协。下面是它的工作原理与背后的理由。
CSP 实际上在阻止什么
当一个 Content-Security-Policy 的 script-src 指令省略了 'unsafe-eval' 和 'unsafe-inline' 时,它就是在告诉浏览器:「不要运行由字符串构建的代码」。正是这条策略阻止了经典的 new Function('...code...')(),而在 v3.1.x 之前,JustZix 正是通过它在 MAIN world 中执行规则与动作 JS 的。受这一限制影响最痛苦的页面就是 facebook.com——它在我们的待办列表里挂着「无法实现」的标签已经好几个月。
三条路径,一个决策
在 v3.2.0 中我们引入了一种分层策略——扩展会依次尝试每条路径,直到其中一条成功:
chrome.userScripts.execute—— 来自 Manifest V3 的原生用户脚本 API。它把代码作为字符串在页面 CSP 世界之外执行,因此可以在任何地方工作,包括最严格的策略。它需要在 manifest 中声明userScripts权限(我们已经声明了),并需要在浏览器扩展设置中一次性开启「允许用户脚本」(Allow user scripts)的开关——这一步由你点击,你始终掌控全局。new Function—— 当页面 CSP 允许'unsafe-eval'时使用的快速、经典路径。大多数普通站点都允许(Google、YouTube、Reddit、Wikipedia、网店),因此 99% 的规则仍然走这条路径,完全无需任何配置。<script src="blob:…">—— 一个后备方案,创建一个本地 Blob URL,并作为经典的script标签注入。当页面 CSP 在script-src中允许blob:时它就能工作——facebook.com 正属于这种情况。即使用户尚未启用「用户脚本」,它也能让代码运行起来。
这在实际中意味着什么
JustZix 的 JS 规则、动作以及 TEMP JS / JS Console 窗口,现在已经可以在那些过去会抛出 EvalError 的页面上运行:
- facebook.com —— 通过 blob-script 后备方案,完全无需配置;
- x.com / twitter.com、github.com、部分银行网站 —— 在启用「用户脚本」之后实现全面覆盖;
- 其他所有地方 —— 一切如旧,继续走经典的
new Function。
如果三条路径都不可行(很罕见,需要页面同时禁止 'unsafe-eval' 和 blob:),JS 面板和 JS Console 窗口会以 8 种语言显示一条清晰的「请启用用户脚本」提示。在浏览器设置里点一下,其余的就会自动完成。
如何启用「用户脚本」
- Chrome / Edge / Opera:
chrome://extensions→ 打开右上角的「开发者模式」(Developer mode) → 找到 JustZix → 切换「允许用户脚本」(Allow user scripts)开关。 - Firefox:
about:addons→ JustZix → 点击「首选项」(Preferences)按钮 → 启用用户脚本选项。
这项权限只需授权一次,之后会被一直记住。我们没有加入自己的同意界面——这是在浏览器设置中由你主动做出的选择,而不是由我们突然弹出的提示。
相较于其他方案,这为何重要
像 Tampermonkey 或 Violentmonkey 这样的用户脚本扩展,要么需要页面允许 'unsafe-eval',要么依赖它们自己的带 eval 的沙箱。JustZix 拥有三条路径,所以当那些扩展抛出「CSP error」并只能等待页面作者发慈悲时,我们已经悄悄选好了另一条路径。这是项目自启动以来最大的一次架构变更——也是真正让目录中 Facebook、X 和 GitHub 的示例合集变得有意义的那一次。
另请参阅
- CSS 和 JavaScript 注入 —— 规则引擎还能做些什么
- 在 CSP 严格的页面上挂接输出控制台 —— 关于日志的同类故事
- JustZix 与 Tampermonkey 对比 —— 完整对比
安装 JustZix——然后在 facebook.com 上毫无借口地编写规则。
为这篇文章评分
暂无评分 — 成为第一个。