
本文详解通过“主世界脚本注入”方式,在 chrome/firefox 扩展中可靠拦截并修改网页原始 fetch 请求的响应数据,解决 content_scripts 沙箱限制导致无法直接 monkey patch 页面全局 fetch 的核心难题。
本文详解通过“主世界脚本注入”方式,在 chrome/firefox 扩展中可靠拦截并修改网页原始 fetch 请求的响应数据,解决 content_scripts 沙箱限制导致无法直接 monkey patch 页面全局 fetch 的核心难题。
在浏览器扩展开发中,content scripts 运行于隔离沙箱环境(isolated world),虽可访问 DOM,但无法直接覆盖页面主线程(main world)的全局 window.fetch——这是导致你代码中 console.log("test2") 在 Firefox 中永不执行、且无法捕获第三方脚本 fetch 调用的根本原因。Chrome 同样受此限制(尤其在 Manifest V3 下隔离更严格)。真正的解决方案是:将 patch 逻辑注入到页面的主执行环境,而非 content script 自身。
✅ 正确做法:动态注入主世界脚本
你需要在 content script 中动态创建 <script></script> 标签,加载一个独立的 JS 文件(如 scripts/attach.js),该文件将被注入到页面的主世界(与网页自身脚本同上下文),从而真正接管 window.fetch:
// content-script.js(运行在沙箱中,仅负责注入)
if (typeof chrome !== 'undefined' && chrome.runtime) {
const script = document.createElement('script');
script.src = chrome.runtime.getURL('scripts/attach.js');
script.onload = () => script.remove();
(document.head || document.documentElement).appendChild(script);
}⚠️ 注意:
chrome.runtime.getURL()仅在已声明web_accessible_resources的 manifest 中有效。务必在manifest.json中配置:"web_accessible_resources": [{ "resources": ["scripts/attach.js"], "matches": ["<all_urls>"] }]
? 主世界 patch 脚本(scripts/attach.js)
此脚本运行在页面主线程,可无阻碍地重写 fetch:
// scripts/attach.js(运行在 main world)
const originalFetch = window.fetch;
window.fetch = async function(...args) {
try {
const response = await originalFetch(...args);
// ✅ 安全克隆并解析 JSON 响应(仅适用于 JSON API)
const cloned = response.clone();
let data;
try {
data = await cloned.json();
console.log('[Extension] Intercepted JSON response:', data);
// ? 在此处修改响应数据(例如添加字段、过滤敏感信息等)
// data.modifiedByExtension = true;
// ? 返回修改后的响应(保持原始状态码、headers)
const newResponse = new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
return newResponse;
} catch (e) {
// 非 JSON 响应(如图片、HTML、二进制流)直接透传,避免破坏
console.warn('[Extension] Skipped non-JSON response');
return response;
}
} catch (err) {
console.error('[Extension] Fetch error:', err);
throw err;
}
};? 关键注意事项
- *不要在主世界脚本中使用 `chrome.
API**:attach.js运行在网页上下文,无扩展权限。如需与 background 或 content script 通信,请使用window.postMessage+chrome.runtime.sendMessage` 桥接。 -
避免重复注入:可在注入前检查
window.__FETCH_PATCHED__标志位,防止多次 patch 导致递归调用。 -
兼容性处理:Firefox 需启用
"run_at": "document_idle"或显式等待 DOM 就绪;Chrome 推荐run_at: "document_start"并监听DOMContentLoaded。 -
性能与稳定性:
.clone().json()会触发完整 body 读取,对大响应可能阻塞;生产环境建议添加 size 限制或超时控制。 -
CSP 兼容性:若目标网站启用了严格 CSP(如
script-src 'self'),动态注入将失败。此时需改用declarativeNetRequest(仅限请求拦截,不支持响应修改)或服务端代理方案。
✅ 总结
劫持网页 fetch 响应的本质,不是“让 content script 更强”,而是绕过沙箱,把补丁精准种进页面自己的执行环境。通过 chrome.runtime.getURL + web_accessible_resources + 动态 <script></script> 注入,你就能稳定、跨浏览器地实现响应级干预——这是当前最成熟、最可控的实践方案。


















