Chrome 正在彻底拆除 Manifest V2:所有绕过手段即将失效

2026-06-10 25 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:10 分钟

如果你还在用 uBlock Origin 的 MV2 版本拦截广告,该做决定了。Google Chrome 已经进入 Manifest V2 扩展支持的最终拆除阶段——不是"逐步过渡",而是彻底封死,包括所有曾经有效的绕过技巧。

为什么这次不同

过去两年,Chrome 对 MV2 的淘汰一直在"温和推进":先是不再接受新的 MV2 扩展提交,然后是逐步在稳定版中弹出迁移提醒。开发者社区也找到了各种绕过方式——修改注册表策略、启用 Developer Mode、使用 Chromium fork 等——让 MV2 扩展继续存活。

但这次的关键信号来自 Chromium 贡献者 Andrey Bershanskiy:他在 w3c WebExtensions Community Group 的 GitHub 仓库中提交了变更,明确指向移除所有绕过机制。这意味着 Chrome 不只是默认禁用 MV2,而是从代码层面确保没有任何开关、策略或 hack 能让 MV2 扩展重新运行。

具体来说,以下绕过手段将全部失效:

绕过方式 当前状态 即将状态
ExtensionSettings 策略强制允许 MV2 有效 将被忽略
Developer Mode 挂载 MV2 扩展 有效 将被阻止
--enable-extensions 启动参数 有效 将被移除
Chromium fork(如 Brave)自行保留 MV2 各 fork 自行决定 上游代码已删除

MV2 到 MV3:核心差异在哪

理解为什么要迁移,先看 MV2 和 MV3 的本质区别:

MV2 的能力模型:扩展拥有持久后台页面(background page),可以长期运行脚本,使用 webRequest API 在请求发出前拦截和修改(blocking webRequest)。这正是 uBlock Origin 高效拦截广告的基础——它在网络层实时过滤每一个请求。

MV3 的限制

  • 后台页面改为 Service Worker,没有持久运行状态,30 秒无活动即休眠
  • webRequest 的 blocking 能力被移除,只能用 declarativeNetRequest(DNR)声明式规则
  • DNR 规则有数量上限(稳定版默认 30,000 条,企业策略可扩展到 150,000)
  • 远程代码执行被禁止,不能动态加载脚本

这些限制直接削弱了广告拦截器的实时过滤能力。uBlock Origin 的规则集远超 30,000 条上限,且依赖动态脚本注入处理复杂规则。

检查你的扩展现状

在迁移之前,先搞清楚自己依赖哪些 MV2 扩展。以下是直接可用的检查方法:

# 列出当前 Chrome 安装的所有扩展及其 manifest 版本
# macOS / Linux
find ~/Library/Application\ Support/Google/Chrome/Default/Extensions \
     ~/.config/google-chrome/Default/Extensions \
     -name "manifest.json" -exec sh -c '
       dir=$(echo "$1" | sed "s|/manifest.json||")
       ver=$(grep -o "\"manifest_version\": [0-9]*" "$1" | grep -o "[0-9]*")
       name=$(grep -o "\"name\": \"[^\"]*\"" "$1" | sed "s/\"name\": //;s/\"/"/g")
       echo "MV$ver | $name | $dir"
     ' _ {} \; 2>/dev/null | sort

# Windows (PowerShell)
Get-ChildItem -Path "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Extensions" `
  -Recurse -Filter "manifest.json" | ForEach-Object {
    $json = Get-Content $_.FullName | ConvertFrom-Json
    "$($json.manifest_version) | $($json.name) | $($_.Directory.FullName)"
  } | Sort-Object

运行后你会看到类似输出:

MV2 | uBlock Origin | /Extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm/1.52.0_0
MV3 | uBlock Origin Lite | /Extensions/ddkjphdeanjmkeiigbmdkhojndkbnlba/1.0_0
MV3 | Password Manager | /Extensions/extensionid/2.1_0

标记为 MV2 的扩展就是需要处理的对象。

实际迁移:一个 MV2 扩展的改造示例

假设你有一个简单的 MV2 扩展,功能是拦截特定域名的请求并注入一段样式。以下是完整的迁移过程:

MV2 版本(即将失效):

// manifest.json (MV2)
{
  "manifest_version": 2,
  "name": "Simple Blocker",
  "version": "1.0",
  "background": {
    "scripts": ["background.js"],
    "persistent": true
  },
  "permissions": [
    "webRequest",
    "webRequestBlocking",
    "<all_urls>"
  ],
  "content_scripts": [
    {
      "matches": ["*://example.com/*"],
      "css": ["hide.css"]
    }
  ]
}
// background.js (MV2) — 实时拦截请求
chrome.webRequest.onBeforeRequest.addListener(
  function(details) {
    if (details.url.includes("ads.example.com")) {
      return { cancel: true };
    }
  },
  { urls: ["<all_urls>"] },
  ["blocking"]
);

迁移到 MV3

// manifest.json (MV3)
{
  "manifest_version": 3,
  "name": "Simple Blocker",
  "version": "2.0",
  "background": {
    "service_worker": "background.js"
  },
  "permissions": [
    "declarativeNetRequest",
    "scripting"
  ],
  "declarative_net_request": {
    "rule_resources": [
      {
        "id": "ad_block_rules",
        "enabled": true,
        "path": "rules.json"
      }
    ]
  },
  "host_permissions": [
    "*://*/*"
  ]
}
// rules.json — 声明式拦截规则
[
  {
    "id": 1,
    "priority": 1,
    "action": { "type": "block" },
    "condition": {
      "urlFilter": "||ads.example.com",
      "resourceTypes": ["script", "image", "sub_frame", "xmlhttprequest"]
    }
  },
  {
    "id": 2,
    "priority": 1,
    "action": { "type": "block" },
    "condition": {
      "urlFilter": "*tracking.example.com/pixel*",
      "resourceTypes": ["image", "xmlhttprequest"]
    }
  }
]
// background.js (MV3) — Service Worker,无持久状态
// 动态注入样式(替代 content_scripts 的部分场景)
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete' && tab.url?.includes('example.com')) {
    chrome.scripting.insertCSS({
      target: { tabId: tabId },
      css: '.ad-banner { display: none !important; }'
    });
  }
});

关键改动总结:

  1. webRequest + blocking → declarativeNetRequest:不再实时拦截,改为预声明规则文件
  2. background.scripts + persistent → service_worker:后台变为事件驱动,无持久页面
  3. content_scriptsscripting API:动态注入更灵活,但需要显式调用
  4. permissions: <all_urls>host_permissions:权限声明拆分,运行时授权更细粒度

广告拦截器的现实选择

对于重度依赖 uBlock Origin 的用户,MV3 的 DNR 规则上限是个硬伤。当前可选方案:

  • uBlock Origin Lite(MV3 版):由同一作者开发,使用 DNR,但功能受限——无法处理复杂 cosmetic filter,规则数量受上限约束。适合轻度拦截需求。
  • AdGuard 浏览器扩展(MV3 版):已迁移到 MV3,支持超过 30,000 条规则(通过多规则集拆分),cosmetic filtering 通过 scripting API 实现。功能比 uBO Lite 更完整。
  • 切换到 Firefox:Firefox 仍支持 MV2 的 blocking webRequest,且承诺不会移除。uBlock Origin 在 Firefox 上功能完整。这是目前最省心的方案。

如果你决定留在 Chrome,可以用以下命令快速安装 AdGuard MV3:

# 直接通过 Chrome Web Store ID 安装(需要 chrome-cli 或手动访问)
# AdGuard MV3 扩展 ID: bgnkhhnnamicmpeenaelnjfhikgbkllg

# macOS 打开扩展页面
open "https://chrome.google.com/webstore/detail/adguard-adblocker/bgnkhhnnamicmpeenaelnjfhikgbkllg"

# 或用命令行检查当前拦截规则数量(AdGuard 安装后)
# 在扩展 Service Worker Console 中执行:
chrome.declarativeNetRequest.getAvailableStaticRuleCount((count) => {
  console.log(`剩余可用静态规则槽位: ${count}`);
});

企业环境怎么办

企业 IT 管理员之前依赖 ExtensionSettings 策略强制保留 MV2 扩展。这条路即将封死。当前可做的准备:

// Windows: 注册表策略路径
// HKLM\Software\Policies\Google\Chrome\ExtensionSettings
// 或 HKLM\Software\Policies\BraveSoftware\Brave\ExtensionSettings

// 策略 JSON 示例(注意:force_installed 对 MV2 即将失效)
{
  "cjpalhdlnbpafiamejdnhcphjbkeiagm": {
    "installation_mode": "force_installed",
    "update_url": "https://clients2.google.com/service/update2/crx"
  },
  "*": {
    "installation_mode": "blocked"
  }
}

// 应迁移为允许 MV3 替代扩展
{
  "ddkjphdeanjmkeiigbmdkhojndkbnlba": {
    "installation_mode": "force_installed",
    "update_url": "https://clients2.google.com/service/update2/crx"
  },
  "bgnkhhnnamicmpeenaelnjfhikgbkllg": {
    "installation_mode": "allowed"
  },
  "*": {
    "installation_mode": "blocked"
  }
}
# 检查当前 Chrome 策略是否生效
# macOS
defaults read com.google.Chrome ExtensionSettings 2>/dev/null | python3 -m json.tool

# Windows
reg query "HKLM\Software\Policies\Google\Chrome" /v ExtensionSettings 2>nul

迁移检查清单

在 MV2 彻底失效之前,完成以下步骤:

  • [ ] 运行扩展扫描脚本,列出所有 MV2 扩展
  • [ ] 为每个 MV2 扩展确认是否有 MV3 替代版本(Web Store 搜索或联系开发者)
  • [ ] 广告拦截器:评估 uBO Lite / AdGuard MV3 / Firefox 三条路
  • [ ] 自研扩展:将 webRequest blocking 改写为 declarativeNetRequest 规则文件
  • [ ] 自研扩展:将 background.page/scripts 改为 service_worker,处理休眠逻辑
  • [ ] 自研扩展:将远程代码加载改为本地打包(MV3 禁止远程脚本)
  • [ ] 企业环境:更新 ExtensionSettings 策略,指向 MV3 扩展 ID
  • [ ] 测试:在 Chrome Canary 中验证所有扩展正常工作(Canary 最先执行新政策)

这次不是"建议迁移",是"强制断电"。提前准备比事后补救成本低得多。


相关推荐