在收到响应时用 JS(chrome 扩展名)修改 <meta> 标签

Modify <meta> tag with JS (chrome extension) on response receiving

我有一个 Chrome 扩展程序,可以将面板添加到浮动 iframe 中的页面(单击扩展程序按钮时)。有一些 JS 代码是从 3rd 方主机下载的,需要在该页面上执行。显然存在 XSS 问题,扩展需要遵守该页面的内容安全策略。

以前我必须处理通过请求 headers 传递的 CSP 指令,并且能够通过在 chrome.webRequest.onHeadersReceived 中设置挂钩来覆盖这些指令。在那里我将我的主机 URL 添加到 content-security-policy headers。有效。 Headers 已被替换,新指令应用于页面,一切正常。

现在我发现通过 <meta> 标签设置 CSP 指令的网站,他们不使用请求 headers。例如,iTunes https://itunes.apple.com/us/app/olympics/id808794344?mt=8 中的应用程序页面就有这样的内容。还有一个名为 web-experience-app/config/environment (?) 的附加元标记,它在某种程度上复制了在带有 http-equiv="Content-Security-Policy".

的标记内容中设置的值

这次我试图将我的主机名添加到 chrome.webNavigation.onCommittedonCompleted 事件侦听器内的元标记中(JS vanilla via chrome.tabs.executeScript)。我还试验了 运行 来自 webrequest 的 onCompleted 侦听器的相同代码(根据 https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webRequest 在生命周期的最后一步)。

当我在加载页面后检查页面时 - 我发现元标记已更改。但是当我点击我的扩展程序开始加载 iframe 并执行 JS - 控制台打印以下错误:

Refused to frame 'https://myhost.com' because it violates the following Content Security Policy directive: "frame-src 'self' *.apple.com itmss: itms-appss: itms-bookss: itms-itunesus: itms-messagess: itms-podcasts: itms-watchs: macappstores: musics: apple-musics:".

即我的标签更新无效。

我有几个问题:第一,我做对了吗?我是否在适当的事件中进行更新?在页面生命周期中何时读取来自元标记的数据内容?标签内容改变后会是auto-applied吗?

自 2018 年 3 月起,Chromium 不允许修改请求的响应主体。 https://bugs.chromium.org/p/chromium/issues/detail?id=487422#c29

"WebRequest API: allow extensions to read response body" 是 2015 年的票。它不在解决的道路上,需要一些 work/help.

--

Firefox 具有允许在应用页面的元指令之前修改响应主体的 webRequest 过滤器实现。 https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webRequest/filterResponseData 但是,我的问题集中在修复 Chrome 扩展。也许 Chrome 有一天会捡到这个。

--

总的来说,Chrome 的扩展构建框架似乎不是构建长期生存软件的可靠途径;浏览器供应商经常更改规则,对新发现的威胁做出反应,没有 up-to-date 支持 cross-browser 标准。

--

就我而言,解决此问题的可能方法是将所有 JS 代码放入扩展的源代码库中。这样就没有第 3 方可以连接以获取和执行 JS(并且冲突 with/violate CSP 规则)。还没有探索这个,因为我希望重用我在我的主浏览器应用程序中使用的代码和交互式组件。

我一直对同样的事情感兴趣,这里有几个方面可能会有所帮助:

  1. chrome.debugger extension API with Fetch (or Network) domain 可用于修改 responseBody: https://chromedevtools.github.io/devtools-protocol/tot/Fetch/
    这是一个示例实现:https://github.com/mr-yt12/Debugger-API-Fetch-example-Chrome-Extension
    但是,我面临 Fetch.requestPaused 未在第一页加载时触发的问题:Chrome Extension Debugger API, Fetch domain attaches/enables too late for the response body to be intercepted
    而且我还没有找到解决方案,除了首先将请求重定向到 'http://google.com/gen_204' 然后更新选项卡。但这会造成闪烁,而且我不确定是否可以使用清单 v3 像这样重定向请求。
  2. 使用调试器 API 时,Chrome 会在顶部显示一条警告,它会更改页面的大小并且不会消失(可能会在调试器分离 5 秒后消失,并且如果用户点击“取消”)。这意味着它主要只适合个人使用或作为开发人员模式扩展分发。将 --silent-debugger-extension-api 标志与 Chrome 结合使用可禁用此警告。
  3. 我已经尝试在 document_start 处注入我的脚本(当元标记尚未创建时)。然后我使用 mutationObserver (也尝试了其他方法)等待元标记,在它被应用或完全创建之前修改它。它以某种方式成功了一次或几次,但可能是巧合或对结果的错误解释。也许值得尝试一下。
  4. 另一个想法(但我认为我没能成功,但也许可行)是在 document_start 处使用 window.stop(),然后以编程方式重写 html 内容。这需要更多的研究。
  5. 元标记 CSP 似乎是在创建元标记后(或在创建元标记时)应用的,然后就无法取消已应用的内容。应该更多地研究如何防止它在完全创建或应用之前应用或修改它。