Kun Direct DOM 扩展示例深度解析:高风险 Isolated World 内容脚本的权限边界、Bridge 协议与生命周期

发布时间:2026/10/10 2:31:08
Kun Direct DOM 扩展示例深度解析:高风险 Isolated World 内容脚本的权限边界、Bridge 协议与生命周期 人工智能AI Agent自主智能体桌面应用MCP Clients【免费下载链接】KunLocal-first AI agent workspace for coding, writing, design, research, and automation — one runtime for desktop GUI and TUI.项目地址https://gitcode.com/gh_mirrors/de/Kun点击查看免费下载Direct DOMhostContentScripts是 Kun 扩展体系中唯一允许直接读写工作台可见 DOM 的高风险替代方案本文以仓库中的 direct-dom 示例 为骨架完整拆解其 manifest 声明、window.kunHost窄桥接协议、documentEnd注入时机、防御式实现与清理策略并结合 Extension API 类型定义 与 Webview/DOM 设计文档 给出源码级佐证。读完你将掌握如何在 Kun 中安全地声明、实现、构建并发布一个受限且可自愈的 Direct DOM 内容脚本。Direct DOM 是什么稳定贡献点之外的最后手段Kun 官方对 Direct DOM 的定位非常明确——它是稳定的 Kun View 之外的例外、高风险替代方案the exceptional, high-risk alternative to a stable Kun View。只有当用户对所选工作区显式授予了hostDom权限时才应安装使用绝不作为默认推荐路径。之所以被定义为高风险是因为内容脚本运行在真实的 Kun 工作台文档里它可以querySelector、读取可见文字并修改可见 DOM但 Kun 无法为宿主元素、selector、CSS class、React ownership 和 layout 提供任何兼容性承诺这些都不属于 Extension APIKun 可以在任意 patch 或 minor 版本中修改它们而不提供适配器。因此官方给出了一条硬性建议如果该行为可以表达为 View 或声明式 action就删除此示例改用稳定贡献点。关于稳定 View、Webview 与 Direct DOM 的能力边界对比可参考 Webview 与 DOM 指南 的完整论述。权限前置条件没有hostDom一切免谈Direct DOM 要生效必须同时满足四个条件见 Webview 与 DOM 指南 第 192–201 行在contributes.hostContentScripts中静态声明script/style、host surface target 和 activation condition所有资源包含在包完整性清单中在 manifest 中请求hostDom权限通过该扩展版本与工作区的受保护权限确认用户显式同意。运行时不能请求注入未声明文件或新 surface安装器必须向用户说明它能读取并修改可见 Kun 工作台内容。这一点在宿主侧有硬约束示例的 host/extension.ts 中activate/deactivate均为空实现注释明确指出Content-script resources are declared statically in the Manifest. The Node host cannot dynamically inject additional scripts, styles, or surfaces——即内容脚本资源完全由 manifest 静态驱动Node 宿主没有动态注入能力。在 manifest 校验层manifest.ts 的manifestReferencedFiles第 290–293 行会收集每个hostContentScripts贡献点声明中的所有scripts与styles路径并经由assertCanonicalPackagePath校验为安全的规范相对路径禁止\0、反斜杠、绝对路径、../越级与不可移植字符同时第 55–57 行拒绝重复的 permissions 声明。workbench:*匹配语义是 Host 表面匹配器不是 URL 通配示例 manifest 中声明matches: [workbench:*]README 特别强调workbench:*is a declarative Host-surface matcher, not a URL glob.它匹配的是非受保护的 workbench 表面包括四个具体取值与 content-scripts.ts 中surface枚举完全一致表面标识含义workbench:code代码工作台表面workbench:design设计工作台表面workbench:write写作工作台表面workbench:connect连接/集成工作台表面相反以下受保护窗口永远不会匹配、也永远不会收到扩展内容脚本设置Settings与引导onboarding流程workspace trust 确认权限确认、审批approval、凭据credential与账号account相关窗口其它安全关键 consent 界面。这些窗口统称为 Protected Surfaces。即使匹配了workbench:*Kun 也绝不向这些安全关键窗口注入内容脚本——这构成了即便扩展恶意也无法触达密钥输入与审批按钮的第一道防线。Manifest 逐字段拆解一个最小可运行的 Direct DOM 声明完整的 kun-extension.json 如下{ $schema: https://kun.dev/schemas/extensions/manifest/v1.json, manifestVersion: 1, apiVersion: 1.0.0, name: direct-dom, publisher: kun-examples, version: 0.1.0, displayName: Direct DOM Warning Badge, description: A high-risk isolated-world content script example with unsupported selectors., license: MIT, engines: { kun: 0.1.0 }, main: dist/host/extension.js, activationEvents: [ onStartup ], contributes: { hostContentScripts: [ { id: warning-badge, matches: [workbench:*], scripts: [dist/content/content.js], styles: [dist/content/content.css], runAt: documentEnd } ] }, permissions: [ hostDom ], stateSchemaVersion: 1 }关键字段逐一说明$schema/manifestVersion: 1/apiVersion: 1.0.0声明 manifest 与 API 版本。Kun 在加载时会用negotiateApiVersion协商 API 版本并检查 capability 需求见 manifest.ts 的assertManifestCompatible不兼容直接以EXTENSION_API_VERSION_UNSUPPORTED等错误拒绝加载。engines.kun: 0.1.0声明兼容的 Kun 引擎版本范围由semver.satisfies校验不符则抛EXTENSION_ENGINE_INCOMPATIBLE。main: dist/host/extension.jsNode 侧入口编译产物本示例中仅做资源生命周期占位。activationEvents: [onStartup]随 Kun 启动即激活。contributes.hostContentScripts核心声明块。每个贡献点包含id如warning-badge、matchesHost 表面匹配器、scripts、styles与runAt。注意脚本与样式路径都是相对包内dist/的静态资源运行时不能追加。permissions: [hostDom]高风险权限的显式请求必须配合用户对工作区的受保护确认才能生效。stateSchemaVersion: 1扩展状态 Schema 版本号。runAt的精确定义documentEnd与documentStartrunAt决定注入时机Kun 给出的语义非常严格Webview 与 DOM 指南 第 203–206 行documentStartKun Main 先把已复验、已读取的声明资源缓存为本次工作台文档的启动计划sandboxed preload 在 renderer 页面脚本执行前同步取得计划、建立 isolated world 并立即执行。若贡献是在当前文档已经启动后才变为 eligibleKun 会安排一次工作台 reload让它在下一份文档真正以documentStart运行——不会偷偷降级成晚注入。documentEnd只在DOMContentLoaded之后执行本示例所用。它可以在已加载工作台中按需启用但绝不会提前到 DOM 尚未就绪时运行。示例 README 的解释正是如此documentEndmeans it never runs beforeDOMContentLoaded;documentStartwould instead be armed by preload for the next document and force a safe reload when first enabled too late.样式遵守同一runAt由 Host 写入带data-kun-extension-styleextension/contribution属性的元素。资源还有明确的大小上限单个脚本/样式文件最多 2 MiB一次注入计划总计最多 8 MiB且只能读取 Manifest 静态声明、经kun-extension://confinement 复验的文件。Isolated World不是 DOM 隔离而是 JS 对象隔离Electron 会在每个 content-script 贡献点专属的 isolated world中执行dist/content/content.js。示例 README 明确列出了该 world 里不存在的东西没有 Node、没有 Electron没有window.kunGui没有 React 对象没有账号密钥、运行时代理 token没有其它扩展的 bridge每个扩展的 isolated world 互相不可见。唯一的桥是window.kunHost示例只通过它读取 Host 派生的 marker/context并在不支持的选择器缺失时上报一个有界诊断。同时直接网络与弹窗原语被禁用。Webview 与 DOM 指南 第 220 行给出了更底层的细节preload 会在该 world 中封闭require、process、module、window.open、fetch、XHR、WebSocket、EventSource、Worker 和sendBeacon工作台自身 CSP 同时阻止远程/inline main-world script、远程样式与远程资源注入。network:hostname并不会给 Direct DOM 开放浏览器网络——需要网络的业务应移到 Node entry 使用 Network Broker或改用 Webview。需要特别强调isolated world 降低的是 JS object/bridge 暴露并不阻止脚本以钓鱼方式修改 UI、读取可见敏感内容或破坏布局因此hostDom始终是高风险 trusted-code 权限这也是权限确认流程存在的意义。窄 Content-script Bridgewindow.kunHost的协议契约kun/extension-api导出KunHostContentScriptApi类型content-scripts.ts 第 34–41 行内容脚本只能看到window.kunHost上的三个方法export interface KunHostContentScriptApi { /** Returns immutable identity/surface metadata derived by Kun, never by the script. */ getContext(): HostContentScriptContext /** Emits one bounded, extension-attributed diagnostic through Electron Main. */ reportDiagnostic(diagnostic: HostContentScriptDiagnostic): Promisevoid /** Disposes this page-local bridge and emits the deactivation event once. */ dispose(): void }getContext()返回的不可变上下文由 Kun 派生、脚本永远无法伪造的元数据content-scripts.ts 第 9–24 行字段类型约束说明apiVersion字面量1Bridge 协议版本extensionId规范化 Extension ID当前扩展身份extensionVersionSemVer当前扩展版本contributionId本地 ID当前贡献点 ID如warning-badgesurface枚举workbench:code/workbench:design/workbench:write/workbench:connectrunAt枚举documentStart/documentEndworkspaceScope字符串 1–128 字符哈希化的工作区作用域marker字符串 3–256 字符Host 派生的 DOM 标记用于标记扩展 rootrawDomCompatibility字面量unsupported显式声明原始 DOM 不在兼容承诺内reportDiagnostic()的有界诊断诊断对象受 Schema 约束第 27–31 行code/^[A-Z][A-Z0-9_]{2,63}$/如SELECTOR_MISSINGmessagetrim 后 1–2,000 字符levelinfo/warning/error默认warning。诊断经 Electron Main 归因到具体扩展且每个 binding 每 10 秒最多 20 条速率限制见 Webview 与 DOM 指南 第 289 行。Bridge 的防冒充设计Bridge 不接受 extension ID、version、workspace 或 permission 作为调用参数——preload 闭包附加 Main 生成的 binding ID/nonceMain 再校验发送 WebContents/main frame、binding、extension、version、contribution、workspace scope 与当前生命周期因此一个 world 无法借 payload 冒充另一个扩展。Bridge 不提供 command、Agent、account、secret、文件、shell、任意 IPC、任意 Host message 或网络能力。过期 world 的晚到 bridge 调用会失败。内容脚本实现剖析防御、有界、可自愈完整的 content.ts 如下逐段解读其工程意图import type { KunHostContentScriptApi } from kun/extension-api declare global { interface Window { readonly kunHost: KunHostContentScriptApi } } // Direct DOM is deliberately outside Extension API SemVer. Every selector below // is an unsupported compatibility dependency and must fail without harming Kun. (() { const context window.kunHost.getContext() const extensionRootId kun-example-direct-dom-warning // Kun never injects content scripts into protected windows. Keep a defensive // check as well so a future host regression cannot make this example render. if (document.documentElement.hasAttribute(data-kun-protected-surface)) return if (document.getElementById(extensionRootId)) return const target document.querySelectorHTMLElement([data-kun-surfaceworkbench-topbar]) ?? document.querySelectorHTMLElement([rolebanner]) if (!target) { void window.kunHost.reportDiagnostic({ code: SELECTOR_MISSING, message: The unsupported workbench top-bar selector was not found., level: warning }) return } const badge document.createElement(span) badge.id extensionRootId badge.dataset.kunExtensionRoot context.marker badge.setAttribute(role, status) badge.textContent Direct DOM example (unsupported selector) target.append(badge) const cleanup (): void { badge.remove() window.removeEventListener(kun-extension-deactivate, cleanup) } window.addEventListener(kun-extension-deactivate, cleanup, { once: true }) window.addEventListener(pagehide, cleanup, { once: true }) })()实现要点与 README 承诺一一对应标记自己的 root创建span时设置id kun-example-direct-dom-warning并用dataset.kunExtensionRoot context.marker写入 Host 派生的 marker——Host 管理的 style 会自动使用同一 marker实现 DOM 归属可追踪。避免 overlay 与交互控件rolestatus语义化宣告其为非交互的状态徽标配套的 content.css 设置了pointer-events: none并约束max-width: 18rem、border-radius: 999px、text-overflow: ellipsis等样式避免破坏工作台布局或拦截用户事件。目标缺失即退出先尝试[data-kun-surfaceworkbench-topbar]回退到[rolebanner]两者都找不到时调用reportDiagnostic上报SELECTOR_MISSINGwarning然后干净返回——绝不抛错、绝不阻塞 Kun 启动。防御受保护表面显式检查document.documentElement.hasAttribute(data-kun-protected-surface)。虽然 Kun 本身不会向受保护窗口注入这层防御确保未来宿主回归也无法让示例在安全界面渲染。去重保护检查document.getElementById(extensionRootId)是否已存在避免重复注入。Host 停用/页面销毁即清理同时监听kun-extension-deactivateHost 在 deactivation 前发送且dispose()也会触发一次该事件与pagehide页面卸载两个事件都是{ once: true }回调移除 badge 并解除自身监听——不留 listener、timer、observer 残留。生命周期纵深Kun 如何保证干净表面即便脚本主动清理Kun 仍采取纵深防御Webview 与 DOM 指南 第 287 行Kun 在 deactivation 前发送kun-extension-deactivate尝试移除匹配 marker 的 Host-managed style/root由于任意脚本还可能留下 listener、timer、observer 或修改过的 Host node不能证明这些副作用已完全逆转以下任一事件都会撤销旧 binding 并 reload 当前工作台文档恢复干净表面disable、uninstall、workspace switch/deactivation、permission change/revocation、version switch/rollback/reload、contribution/surface 变化Main 每 2 秒重新验证当前 package/version/workspace/grant/declaration以捕获由 CLI 或其它客户端完成的外部撤销审批待处理pending/submitting期间Kun 同样会撤销当前工作台的 content-script binding 并做一次干净 reload第 268 行且审批按钮只接受 Chromium 标记为isTrusted的真实用户事件HTMLElement.click()或脚本派发的事件被忽略。这也解释了为什么 content script 必须主动在kun-extension-deactivate与pagehide中清理——它是对 reload 兜底机制的锦上添花但绝非可依赖的单一保障。构建、校验与打包命令行实操package.json 提供了四个标准脚本# 类型检查不产出 npm run typecheck # 构建tsc 编译 复制静态资源 npm run build # 校验用仓库 CLI 校验扩展清单 npm run validate # 打包构建后生成扩展包 npm run pack逐条说明build执行tsc -p tsconfig.json将src/编译到dist/随后执行node ../copy-static-assets.mjs仓库根下 scripts 目录中扩展示例共享的静态资源复制脚本。tsconfig.json 采用ES2022NodeNext模块解析、strict: truelib同时包含ES2022与DOM内容脚本需要 DOM 类型。validate执行node ../run-repository-kun-cli.mjs extension validate .在仓库内直接用 Kun CLI 校验清单可提前暴露 manifest 结构、路径安全或权限声明问题。pack先build再node ../run-repository-kun-cli.mjs extension pack .产出可安装的扩展包。构建产物必须与 manifest 声明一致main指向dist/host/extension.js内容脚本指向dist/content/content.js、样式指向dist/content/content.css——任何声明与产物不匹配都会在 manifest 校验manifestReferencedFiles阶段被拦截。兼容性铁律与发布前检查清单示例 README 的最后一段是 Direct DOM 使用者的免责声明The selectors and host layout are unsupported compatibility dependencies: Kun may change them in any patch or minor release.选择器与宿主布局属于不受支持的兼容性依赖Kun 可以在任意 patch/minor 中变更而不提供 adapter选择器失效属于扩展的不受支持依赖不是稳定 API 回归。因此内容脚本应遵循 Webview 与 DOM 指南 第 278–285 行给出的行为准则只匹配公开支持的 host surface target对 selector 缺失无害退出并记录 bounded diagnostic从getContext().marker取得标记为自己创建的 root 使用data-kun-extension-root保持 mutation observer、listener 和 timer 有界不覆盖安全/账号/审批 UI在 deactivation 消息中主动清理。发布前检查清单第 291–299 行还包括若能改用 stable action/View/Webview 就删除hostDomWebview 无 Node、无 custom preload、无 direct network、无 remote code所有资源仅从kun-extension://和声明 roots 加载消息/状态有 Schema、size/rate limit 与 disposal主题、locale、keyboard、focus、error/reconnect 均已测试账号、审批和秘密只使用 protected surface/Broker。小结示例本身即最佳实践模板direct-dom示例的价值不在于功能它只是一个警示徽标而在于它把高风险能力的正确姿势浓缩成了 60 行代码 一份 33 行的 manifest权限显式声明、匹配面收敛到非受保护 workbench 表面、依赖窄桥而非特权 API、目标缺失静默退出并上报有界诊断、主动清理与被动 reload 兜底并存、并把所有选择器依赖明示为不受支持。任何需要在 Kun 中直操作 DOM 的扩展都应先对照本示例与 Webview 与 DOM 指南、Extension API Bridge 类型 完成同样的风险自检再决定是否真的需要hostDom。赞分享人工智能AI Agent自主智能体桌面应用MCP Clients【免费下载链接】KunLocal-first AI agent workspace for coding, writing, design, research, and automation — one runtime for desktop GUI and TUI.项目地址https://gitcode.com/gh_mirrors/de/Kun点击查看免费下载相关推荐Velero 存储位置深度解析BackupStorageLocation 与 VolumeSnapshotLocation 的多区域、多凭证实战配置Velero 存储位置深度解析BackupStorageLocation 与 VolumeSnapshotLocation 的多区域、多凭证实战配置 本文以人工智能AI Agent自主智能体桌面应用MCP ClientsPyTorch TorchElastic Elastic Agent 深度解析Worker 生命周期管理、容错与弹性扩展PyTorch TorchElastic Elastic Agent 深度解析Worker 生命周期管理、容错与弹性扩展 本文以 PyTorch 仓库中 do人工智能机器学习深度学习分布式训练模型编译vex 高级 API 完全指南DOM 结构、实例生命周期与安全内容策略vex 高级 API 完全指南DOM 结构、实例生命周期与安全内容策略 本指南以 docs/api/3 Advanced.md https://link.giUI组件上一篇Krew 插件清单管理kubectl krew list 的使用、原理与备份恢复实战下一篇ScriptCat 云同步实现解析多 Provider 下的 best-effort 同步架构、digest 对账与冲突收敛机制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询