You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Manifest V3扩展向data URI iframe注入脚本报web_accessible_resources错误

问题根因

这不是配置错误,也不是偶发bug,是Chrome对Manifest V3扩展的既定安全限制:

  • data: URI格式的iframe属于不透明源(opaque origin),对应的window.origin值为null
  • web_accessible_resources的匹配规则(即使配置为<all_urls>)不会对这类无有效宿主的null源开放chrome-extension://协议资源的加载权限
  • 原逻辑是在页面主世界插入带扩展资源src的script标签,该请求由null源的页面上下文发起,会直接被Chrome的安全策略拦截,触发报错。非data URI的常规源因为能被WAR规则匹配,所以可以正常加载。
可用替代方案

优先选择第一种方案,改动最小、兼容性最好,不需要额外申请权限。

方案1:内联注入脚本内容(推荐)

核心逻辑是避开主世界发起chrome-extension://请求的环节:在content script的隔离上下文先读取扩展内payload脚本的文本内容,再直接以内联形式插入到页面主世界,完全绕开WAR校验逻辑。
不需要修改现有manifest配置,直接替换content-script.js代码即可:

// 隔离上下文内请求扩展资源不受WAR规则限制
fetch(chrome.runtime.getURL('/src/dest/payload-min.js'))
  .then(resp => resp.text())
  .then(payloadCode => {
    const script = document.createElement('script')
    script.className = 'myScriptClass'
    // 直接写入脚本内容,不设置src属性
    script.textContent = payloadCode
    const injectTarget = document.head || document.documentElement
    injectTarget.appendChild(script)
    // 注入执行完成后可移除标签,减少DOM冗余
    script.remove()
  })

该方案在所有frame类型(常规源iframe、data URI iframe、about:blank iframe)下均可正常运行。

方案2:使用chrome.scripting API直接注入主世界

如果不想用内联注入的形式,可以用MV3原生的脚本注入API,直接把payload注入到页面主世界,不需要手动创建script标签,也不依赖WAR配置。
首先修改manifest.json:

  1. 在permissions数组中新增"scripting"权限
  2. 确保host_permissions包含"<all_urls>"(当前配置已满足)

之后修改content-script.js逻辑,针对data URI源走API注入逻辑:

// data:、about:blank等特殊源的origin均为null
const isSpecialOrigin = window.origin === 'null'

if (isSpecialOrigin) {
  // 获取当前tab信息,向当前帧注入主世界脚本
  chrome.tabs.getCurrent(tab => {
    chrome.runtime.sendMessage({type: 'getFrameId'}, resp => {
      chrome.scripting.executeScript({
        target: { tabId: tab.id, frameIds: [resp.frameId] },
        files: ['/src/dest/payload-min.js'],
        world: 'MAIN',
        injectImmediately: true
      })
    })
  })
} else {
  // 常规源保留原有逻辑即可
  const script = document.createElement('script')
  script.className = 'myScriptClass'
  script.src = chrome.runtime.getURL('/src/dest/payload-min.js')
  ;(document.head || document.documentElement).appendChild(script)
}

对应的background.js中补充消息监听,返回当前帧ID:

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.type === 'getFrameId') {
    sendResponse({frameId: sender.frameId})
  }
  return true
})
注意事项

不要尝试把data URI加入WAR的matches列表,Chrome不支持在WAR规则中匹配null源,这类配置会在扩展加载时直接被忽略。


内容的提问来源于stack exchange,提问作者user19487433

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 11:15:29