首页 / 浏览器扩展开发入门教程 / 禁止远程代码与发布规范

浏览器扩展开发入门教程

禁止远程代码与发布规范

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

远程代码remotely hosted code打包商店审查发布规范扩展安全MV3

本节目标:学完你能判断哪些写法会被判定为”远程托管代码”、知道把所有逻辑打包进扩展的合规替代方案,并了解商店审查时主要卡哪些安全关。

上一节讲的是技术层面:CSP 把扩展能执行的代码锁在包内部。这一节讲制度层面:Chrome Web Store 在审核时,会专门检查你的扩展有没有”运行时从外部拉代码”。两条线合起来,就是 Manifest V3 最核心的一条安全铁律——所有会执行的 JS,必须随扩展包一起提交、一起过审

45-1 什么是远程托管代码

“远程托管代码”(remotely hosted code),指的是扩展在用户浏览器里运行时,从扩展包之外的地址获取并执行的 JavaScript。注意关键词:“执行”。从服务器拉数据、拉配置、拉图片,这些都不算;算的是”拉回来一段能跑的代码再执行它”。

Chrome 的禁令非常明确:扩展包里必须包含它会执行的所有代码。审查团队审的是你提交的那个包,用户装的也必须是那个包。中间不能有任何”运行时再悄悄下载一段脚本”的口子。

这条规则是整个 MV3 安全模型的基石。没有它,CSP 再严也只是纸面文章——攻击者完全可以提交一份干净包过审,然后让扩展运行时从自己服务器拉恶意代码。把远程代码这条路堵死,审查才真正有意义。

45-2 哪些写法会踩线

下面几类,是商店审核时重点盯、也最容易让新手翻车的”远程托管代码”形态:

用 eval / new Function 执行远程字符串。 比如先 fetch 一段脚本文本,再 eval 它;或者用 new Function(远程字符串)。这是最典型的违规,eval 在扩展里本来就被 CSP 封死,配合远程来源更是双重违规。

动态加载远程 <script> 在页面里插入 <script src="https://你的服务器/xxx.js">,或从 CDN 引入库。上一节讲过 CSP 会拦,这里再说一遍:它不仅技术上跑不起来,提交商店也会被直接打回。

运行时从服务器取代码注入页面。 比如用 chrome.scripting.executeScriptcode 字段,传进去的字符串是从远程接口现拉的。只要那段代码不是写死在你提交的文件里,就违规。

靠远程配置改变扩展行为逻辑。 这是更隐蔽的一类。代码本体在包里,但关键分支、功能开关完全由远程下发的”代码段”决定。审核认定:实际行为不在提交物中,等于变相远程托管。

Warning

有个误区要避开:有人以为”我把代码放进沙盒 iframe 从远程加载就行”。不行。沙盒只是隔离环境,不能成为绕开远程代码禁令的后门。沙盒里跑的代码同样得在包内。

45-3 第三方库必须跟着打包

很多项目离不开 jQuery、某个工具库,或者 React 之类的框架。在 MV3 下,正确做法是:把库的 .js 文件下载进扩展目录,像引用自己代码一样引用它。

<!-- 正确:库文件随扩展打包,放在扩展目录里 -->
<script src="./vendor/jquery.min.js"></script>
<script src="./content-script.js"></script>
{
  "manifest_version": 3,
  "name": "My extension",
  "content_scripts": [
    {
      "matches": ["https://example.com/*"],
      "js": ["vendor/jquery.min.js", "content-script.js"]
    }
  ]
}

这样库和你的代码一起提交、一起过审,来源完全可见。千万别图省事写 https://code.jquery.com/...,那会被当成远程托管直接拒。

向页面注入脚本时,用 chrome.scripting.executeScriptfiles 数组,把要注入的文件放在扩展包内:

chrome.scripting.executeScript({
  target: { tabId: tab.id },
  files: ['vendor/jquery.min.js', 'content-script.js']
});

这就合规——文件是打包进去的,不是运行时现拉的。

45-4 想动态执行?用 func 而不是 code 字符串

如果你需要”针对不同情况注入不同逻辑”,别用 code 传一段拼接出来的字符串。MV3 提供了更安全的 func + args 方式:函数本体写在你的源码里(随包提交),运行时的可变部分只通过 args 当数据传进去。

async function getCurrentTab() {
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  return tab;
}

let tab = await getCurrentTab();

function showAlert(givenName) {
  alert(`Hello, ${givenName}`);
}

let name = 'World';
chrome.scripting.executeScript({
  target: { tabId: tab.id },
  func: showAlert,
  args: [name]
});

这里 showAlert 是写死在提交文件里的函数,name 只是普通数据。可执行的逻辑始终在包内,符合要求。对比一下:如果你把 showAlert 的内容改成从接口拉、再拼成 code 字符串传进去,那就违规了。

Tip

一句话记牢:func 传函数、args 传数据,逻辑永远写在提交的源码里;code 字段只适合传静态、写死的字符串,绝不接远程内容。

45-5 合规的三类替代思路

当你的需求原本依赖”远程代码”时,下面三种思路是 Chrome 官方推荐的合规替代,按场景选用。

配置驱动,逻辑本地。 服务器只下发数据或配置(比如开关、阈值、文案),真正判断和执行的分支写在扩展本地。扩展读到配置后,用本地代码做决定。数据可变、逻辑不变,行为仍在审查范围内。

逻辑外置成远程服务。 别让扩展自己算,把”算”搬到你的服务器,扩展只负责调用接口拿结果。比如要翻译一段文字,扩展把原文发给翻译服务,拿回译文展示——它执行的是”发起请求、渲染结果”的本地代码,翻译能力在远端服务里,这不叫远程托管代码。

不可信代码放沙盒。 确实需要执行来源不完全可控的代码(如用户模板),放进沙盒页隔离运行,且沙盒代码也必须打包在扩展内,不能从远程拉。

这三种的共同点:最终在浏览器里 eval、执行的脚本,全部在提交包中可见。变的是数据,不是代码。

45-6 商店审查关注哪些安全关

远程代码禁令只是审核的一关。把扩展提交到 Chrome Web Store 时,审查还会重点看下面这些安全要求。提前心里有数,能少走很多弯路。

单一用途原则。 扩展的功能要聚焦、明确,且和商店详情页描述一致。一个”网页截图”扩展突然要去读你的全部浏览记录,会被质疑。权限和功能要对得上。

权限最小化。 申请的每个权限都要能说清用途。申请了 history 却只用来看标题,审查会要求你删掉多余权限。前面章节讲的最小权限原则,在这里是硬指标。

代码可读性。 提交的可执行代码应当可以被审查。过度混淆、刻意让逻辑难以辨认的代码会被要求提供可读源码。正常的压缩(minify)一般没问题,但用混淆手段故意藏逻辑,会被打回。

用户数据处理。 涉及用户数据(账号、浏览行为、位置等),必须有清晰的披露:收集什么、为什么、怎么用、是否外传。隐私政策该有的要有,且要和实际行为一致,不能挂羊头卖狗肉。

功能与描述一致。 扩展实际做的事不能超出、偏离你在详情页写的功能。诱导下载、暗藏额外行为,都是拒绝理由。

Note

这些要求不是写了清单就能过,而是”你的代码 + 描述 + 权限 + 隐私说明”要自洽。审查看的是整体画像,不是单看某个字段。

45-7 哪些做法最容易被打回

结合上面几节,把高频”被拒原因”列出来,写的时候绕着走:

  • 运行时 evalnew Function 执行来自网络的字符串。
  • 从 CDN 或自有服务器动态加载脚本文件。
  • 提交的是混淆到无法审查的代码,又给不出可读版本。
  • 申请了大量用不上的权限,和功能明显不匹配。
  • 详情页描述轻描淡写,扩展实际在后台做别的事。
  • 把关键功能逻辑藏在远程下发的”配置/脚本”里。
Tip

如果你拿不准某段写法算不算远程托管,用这个自检标准:把扩展包解压出来,里面是不是能找到用户运行时会执行的全部 JS?能找到,就合规;找不到(要靠联网才拿到),就违规。

45-8 落到工程习惯上

把这一节和上一节合起来,好的扩展工程习惯是这样的:

  • 所有 JS 进包,第三方库下载到 vendor/ 再引用,不挂外链。
  • 动态逻辑用 func + args,或”远程取数据、本地算结果”。
  • 清单里 content_security_policy 保持默认或只做有限收紧,绝不放开远程源和 eval。
  • 申请权限时逐条想清楚用途,能不申请的就不申请。
  • 提交前自查:包内能否找到全部会执行的代码。

说实话,这些约束刚接触会觉得束手束脚。但换成用户视角就明白:一个能读你账号、能改你网页的扩展,如果还能偷偷从服务器拉未知代码,那风险是不可控的。Chrome 用技术(CSP)加流程(审核禁令)双重锁死它,护的是所有装扩展的人。你顺着这套规则写,反而省掉了自己兜底安全的海量工作。

到这一节,模块九”安全与策略”就讲完了。下一模块我们进入调试:怎么把扩展加载进浏览器、怎么在各组件里排错。