← 全部文章

API 与辅助工具

JustZix 如何在 CSP 严格的页面上注入代码

有些页面的 Content-Security-Policy 严格到不会执行任何不是它作者写的脚本。可 JustZix 仍然能把你的 JS 注入进去,并把 Output Console 挂到页面的 console.log 上。本文解释这是怎么做到的 —— 以及为什么第一个版本做不到。

CSP 是什么、为什么它碍事

Content-Security-Policy 是一个 HTTP 头,页面用它声明脚本可以从哪里加载。一个典型的严格策略是 script-src 'self' —— 「只执行来自我自己域名的脚本」。这样的策略会阻止内联的 <script>:如果你往 DOM 里注入一个 <script>代码...</script> 标签,浏览器不会执行它。GitHub、银行仪表盘和许多企业网站就是这样工作的。

第一种做法 —— 以及一次回归

Output Console 钩子的一个早期版本(v2.13.72-73)正是通过加到 <head> 里的一个内联 <script> 来注入代码。在普通页面上它有效。在带 script-src 'self' 的页面上浏览器静默拒绝那个脚本 —— 钩子从未挂上,Output Console 保持为空。这是一次回归:一个在「演示里」有效的功能,恰恰在开发者最需要它的地方失败了。

修复 —— chrome.scripting.executeScript

解决方案(v2.13.74)不再注入一个 <script> 标签。相反,扩展的 service worker 调用 chrome.scripting.executeScript。这就是关键区别:这个脚本以扩展的权限运行,而不是页面级别。页面的 CSP 不适用于它 —— 浏览器把它当作用户在安装时同意过的、可信扩展的代码。

MAIN world 对 ISOLATED world

扩展的 content script 默认活在一个「隔离世界」(ISOLATED)里 —— 它们有自己的 window,与页面分开。这很安全,但当你想挂到页面真正的 console.log 或碰它的全局变量时就没用了。

所以钩子落在 MAIN world 里 —— 页面代码所活的同一个 JavaScript 上下文。在那里它能包装 console.log/warn/error、挂上 error 和 unhandledrejection 监听器,并精确看到页面所看到的。

世界之间的一座桥 —— postMessage

MAIN world 里的钩子捕获日志,但 Output Console 窗口本身是由 ISOLATED world 里的一个 content script 渲染的。两个世界不共享变量 —— 需要一座桥。那座桥是 window.postMessage:

  1. MAIN world 的钩子拦截一条 console.log 条目。
  2. 它序列化参数并用一个带标签的载荷调用 window.postMessage。
  3. ISOLATED 的 content script 监听 message,按标签过滤,并把条目渲染到 Output Console 窗口里。

postMessage 是少数几个穿越世界边界的通道之一 —— 而且它不违反 CSP 就做到这点,因为它不是脚本执行,只是消息传递。

这在实践中意味着什么

Output Console 和 JS 注入在那些经典内联脚本伎俩会失败的页面上有效 —— GitHub、银行仪表盘、带硬 CSP 的企业内网。你什么都不用配置;扩展自己选这条路。

限制 —— CSP 仍然不会允许什么

v3.2.0 更新 —— 规则、动作和 TEMP 窗口也一样

上面的机制说的是 Output Console 钩子 —— 扩展如何监听页面的 console.log。执行你的 JS 规则、动作和 TEMP JS 窗口是另一条路径 —— 而且它过去也只在 CSP 允许 'unsafe-eval' 的页面上才能工作。在 v3.2.0 中我们把同样的「分层策略」移植到了第二条路径上:尝试顺序是 chrome.userScripts.execute → new Function → <script src="blob:…">。现在规则、动作和 JS pane / JS Console 即使在 Facebook 上也能运行(通过 blob 回退),在完全 CSP 严格的站点上也能运行(通过 userScripts,在一次性「允许用户脚本」选择加入之后)。完整介绍:JustZix JavaScript 规则现在在 Facebook、X 和 GitHub 上也能用。

另见

安装 JustZix —— 即便页面说「不」,也能注入代码。

为这篇文章评分

暂无评分 — 成为第一个。

自己动手试试

安装 JustZix,粘贴本文中的任意代码片段。两分钟,从零到一条在你所有设备上生效的规则。

获取 JustZix

功能 · 工作原理 · 示例 · 应用场景