← 全部文章

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、挂上 errorunhandledrejection 监听器,并精确看到页面所看到的。

世界之间的一座桥 —— 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.executenew Function<script src="blob:…">。现在规则、动作和 JS pane / JS Console 即使在 Facebook 上也能运行(通过 blob 回退),在完全 CSP 严格的站点上也能运行(通过 userScripts,在一次性「允许用户脚本」选择加入之后)。完整介绍:JustZix JavaScript 规则现在在 Facebook、X 和 GitHub 上也能用

另见

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

为这篇文章评分

暂无评分 — 成为第一个。

自己动手试试

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

获取 JustZix

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