首页 / WXT 浏览器扩展框架教程 / 权限:最小够用原则

WXT 浏览器扩展框架教程

权限:最小够用原则

本教程共 45 篇 · 第 21 篇 · 更新于 2026-08-13 · 约 3 分钟阅读

WXT权限permissionshost_permissions安全

本节目标:分清三类权限声明,学会在 wxt.config.ts 里声明权限,并掌握「最小够用」的设计步骤。

权限是什么

权限(permissions)是扩展向浏览器申请的「能力清单」。用户安装扩展时,浏览器会展示这些声明。权限越多,警告越吓人,上架审核的风险也越高。所以原则只有一个:够用就好,越少越好。

WXT 项目里没有 manifest.json,权限统一写在 wxt.config.tsmanifest 字段中(manifest 生成机制见 §25):

export default defineConfig({
  manifest: {
    permissions: ['storage', 'tabs'],
  },
});

三类声明别搞混

新手最容易混的是这三个概念。它们相关,但不是一回事:

  • permissions:允许调用某类扩展 API,比如 storagetabsscripting
  • host_permissions:允许对某些站点做受限操作或跨源请求,比如 https://www.google.com/*
  • 内容脚本的 matches:决定脚本自动注入到哪些页面,如 §11 所述。
export default defineConfig({
  manifest: {
    permissions: ['scripting'],
    host_permissions: ['https://api.example.com/*'],
  },
});

一个功能常常要同时声明好几类。比如用 scripting.executeScript 往网页注入代码,既要 scripting API 权限,也要对应页面的授权。反过来,声明了 host permission 不代表自动有内容脚本,matches 是另一份独立声明。

Note

MV3 里 host_permissions 是独立字段;MV2 没有这个字段,主机权限直接以 URL 形式混在 permissions 数组里写。WXT 构建时会按目标清单版本自动转换,但写配置时心里要有数。

WXT 会自动加哪些权限

大部分权限要手动声明,只有两种例外:

  • 开发模式(dev)下自动加 tabsscripting,用来支持热重载。
  • 项目里有 sidepanel 入口时,自动加 sidepanel 权限。

所以「开发时没写也有」的权限,打包后可能就没有了。一切以产物里的 manifest 为准。

不同浏览器,不同权限

各家浏览器支持的权限不一样。同一个字段,Chrome 和 Firefox 往往要给出不同列表。用 manifest 函数按浏览器分支:

export default defineConfig({
  manifest: ({ browser }) => ({
    permissions:
      browser === 'chrome'
        ? ['storage', 'favicon', 'declarativeNetRequest']
        : ['storage', 'webRequest'],
  }),
});

同理,MV2 和 MV3 需要的 host_permissions 也可能不同,可以用 manifestVersion 分支。

最小权限设计六步

mkext 项目教程总结了一份开发新功能前的自问清单,按顺序回答:

  1. 功能必须在哪个运行环境执行?(后台、内容脚本、弹窗……)
  2. 需要哪个浏览器 API?
  3. 只操作用户当前主动选择的标签页,还是长期匹配固定站点?
  4. 能否把范围缩小到指定域名和路径?
  5. 权限是安装时必需,还是可以做成 optional permission,需要时再请求?
  6. UI 有没有向用户解释读取和使用了哪些数据?

不要先加一堆宽泛权限,再逐个试哪个能消掉报错。权限收敛是设计出来的,不是试出来的。

host_permissions 从环境变量动态取

站点列表写死很难维护。mkext 的做法是从环境变量取 origin,再拼成权限:

// wxt.config.ts
const getAuthHostPermission = () => {
  const authUrl = new URL(
    import.meta.env.VITE_AUTH_URL ?? 'http://localhost:3000',
  );
  return `${authUrl.origin}/*`;
};

export default defineConfig({
  manifest: {
    host_permissions: [
      getAuthHostPermission(),
      'https://api.example.com/*',
    ],
  },
});

环境变量是 https://app.example.com/path 时,权限会收敛成 https://app.example.com/*。换环境只改配置,不动代码。

验证最终权限

WXT 会按入口自动生成一部分 manifest 字段,你手写的只是其中一部分。跑一次构建,打开产物确认最终结果:

wxt build
# 检查 .output/chrome-mv3/manifest.json
Tip

内容脚本的 matches 与权限声明相互独立,但用户感知相同:都是「扩展能碰到哪些网站」。设计时把它们放在一起考虑,站点范围保持最小,如 §11 所述。

小结

  • permissions / host_permissions / content script 的 matches 作用域不同,别混为一谈。
  • 最小权限是原则:先不加权限开发,最后按需补,optional permissions 给运行时兜底。
  • 权限收敛是设计出来的,不是试出来的——开发新功能前先过一遍自问清单。