鸿蒙 PC Markdown 编辑器预览安全:CSP、DOMPurify 与权限收缩

发布时间:2026/7/26 6:07:21

鸿蒙 PC Markdown 编辑器预览安全:CSP、DOMPurify 与权限收缩 鸿蒙 PC Markdown 编辑器预览安全CSP、DOMPurify 与权限收缩本文从不可信 Markdown 的威胁模型出发说明渲染、DOM、URL、ArkWeb 能力和原生 Bridge 如何形成分层防护。完整示例代码https://gitcode.com/VON-/codex_md_oh。Markdown 预览为什么是安全边界Markdown 编辑器通常会把文本转成 HTML。如果直接将渲染结果赋给innerHTML用户打开的文档就可能携带脚本、事件属性、表单、iframe 或危险链接。在鸿蒙 PC 端预览还运行在与原生 Bridge 相邻的 ArkWeb 环境中因此必须采用多层防护不能只依赖某一个正则替换。第一层用 CSP 默认禁止外部能力ArkWeb 加载的 HTML 内置了如下 CSPmetahttp-equivContent-Security-Policycontentdefault-src none; script-src self unsafe-inline; style-src self unsafe-inline; img-src data: resource: file:; font-src data:; connect-src none; object-src none; base-uri none; form-action none/代码来源web-editor/index.htmldefault-src none建立默认拒绝策略connect-src none禁止 Web 网络连接object-src none、base-uri none和form-action none分别阻止对象嵌入、基地址篡改和表单提交。当前为了支持单 HTML 内联包script-src与style-src仍包含unsafe-inline。这是已知折中不应被描述为理想的最终 CSP。后续可以评估 hash/nonce 或安全的多资源加载策略。第二层渲染器不接受原始 HTMLconstmarkdownRenderernewMarkdownIt({html:false,linkify:true,typographer:false,breaks:false});代码来源web-editor/src/main.tshtml: false使 Markdown 文档中的原始 HTML 不会被当成可执行页面结构。但是安全设计不能假定渲染器永远无缺陷因此仍需要输出净化。第三层DOMPurify 净化与链接隔离functionsanitizeMarkdown(content:string):string{constunsafeHtmlmarkdownRenderer.render(content);returnDOMPurify.sanitize(unsafeHtml,{USE_PROFILES:{html:true},FORBID_TAGS:[style,iframe,object,embed,form],FORBID_ATTR:[style]});}functionrenderPreview(content:string):void{preview.innerHTMLsanitizeMarkdown(content);preview.querySelectorAllHTMLAnchorElement(a).forEach((link){link.target_blank;link.relnoopener noreferrer;link.addEventListener(click,(event)event.preventDefault());});previewDirtyfalse;}代码来源web-editor/src/main.tsDOMPurify 使用 HTML 白名单模式另外禁止可以嵌入外部上下文的标签和行内样式。预览区链接补上noopener noreferrer并在当前技术验证中默认拦截点击避免文档内容直接发起跳转。鸿蒙 PC 离线运行截图安全边界不会在界面上额外显示提示。下图是内联编辑器在鸿蒙 PC / 2in1 模拟器中的离线运行载体ArkWeb 无在线图片、文件或定位权限只暴露受限 Bridge。已验证与未验证项当前 14 项 Playwright 回归已经覆盖 Markdown 中的script、危险链接、导出标题注入、独立 HTML、打印媒体 DOM 和生产单文件包。预览与导出共用sanitizeMarkdown避免两条渲染链路出现安全规则漂移。鸿蒙原生侧已经接入 DocumentViewPicker、WebPrintDocumentAdapter 和 Print Kit并保持在线图片、文件访问、地理位置与 DOM Storage 关闭。系统 PDF 产物、本地图片真实 URI、只读目标和空间不足仍需设备测试因此当前只能判断核心边界成立不能推导为所有场景无风险。先把 Markdown 当作不可信输入本地文件不等于可信文件。Markdown 可能来自代码仓库、邮件附件、聊天工具、下载目录或第三方同步盘作者与打开文件的用户并不一定相同。攻击者可以把恶意内容伪装成普通文档等待用户在拥有本地文件权限的编辑器中打开。威胁模型至少包含原始 HTML 中的script、事件属性和可执行 URL。iframe、object、表单等加载外部上下文或提交数据的节点。Markdown 链接使用javascript:、data:等危险协议。图片和样式触发网络请求泄露文档打开时间、IP 或标识。导出路径绕过预览净化生成可执行的独立 HTML。预览内容借助 Bridge 调用原生文件、打印或保存能力。超大或特殊结构文档造成解析、DOM 和布局资源耗尽。安全目标不是让 Markdown 支持所有浏览器能力而是在保证常用排版的前提下默认拒绝执行、连接、提交和越权文件访问。多层防护为什么不能合并成一层Markdown 渲染器、DOMPurify、CSP、ArkWeb 配置和 Bridge 白名单分别保护不同阶段不可信 Markdown → markdown-it禁用原始 HTML → DOMPurify净化生成 HTML → 受控 DOM 插入与链接处理 → CSP限制页面资源和连接 → ArkWeb 权限收缩限制 Web 系统能力 → Bridge 白名单限制原生入口渲染器配置可以减少危险输入面但无法保证所有插件未来都安全DOMPurify 处理输出 DOM却不能阻止应用自己的脚本主动发起连接CSP 限制浏览器加载却不决定原生代理暴露什么Bridge 白名单保护原生方法却不负责清理 HTML。分层设计使单点失误不直接变成完整权限突破。CSP 要从默认拒绝开始default-src none的意义是新增资源类型默认被阻止而不是默认继承一个宽松来源。随后只为当前确实需要的能力开放最小集合脚本和样式来自内联生产包图片只允许 data、resource、file连接明确为 none对象、base 和表单均禁止。当前单 HTML 包要求unsafe-inline这是风险折中。它意味着 CSP 不能阻止页面内被注入的任意内联脚本因此安全性更依赖构建资源完整性和 DOM 净化。更强方案可以考虑基于 hash 的script-src、分离的本地只读资源或 ArkWeb 支持的 nonce 机制但需要验证 rawfile 加载和生产构建是否稳定。CSP 不应只写在模板里就算完成。生产打包可能重写 HTML测试应加载最终rawfile/editor/index.html检查策略仍存在并验证没有外部脚本、样式和连接。禁用原始 HTML仍需净化输出markdown-it的html: false会把用户写下的原始 HTML 当作文本这已经阻断大量直接注入。但 Markdown 本身仍能生成链接、图片等 HTML未来插件还可能引入表格、脚注、任务列表或数学公式。渲染器和插件中的漏洞也不能被排除。DOMPurify 位于渲染后、插入前使用 HTML profile 并额外禁止 style、iframe、object、embed 和 form。禁用行内 style 可以减少 CSS 覆盖和外部资源技巧但会限制用户自定义排版这是本地文档安全优先于任意 HTML 兼容的产品选择。净化结果必须作为唯一可插入预览 DOM 的内容。不要在另一个功能中直接调用markdownRenderer.render()后赋给innerHTML也不要先插入再清理危险节点一旦进入活动文档某些副作用可能已经发生。URL 协议需要单独审查HTML 标签安全不代表 URL 安全。链接和图片的href、src可以携带协议Markdown 相对路径还会根据页面 base URL 解析。当前预览为链接设置_blank、noopener noreferrer并拦截点击避免文档直接导航。以后若允许打开链接应由受控处理器解析 URL建立协议白名单常规网页可允许https本地文件和自定义协议需要用户确认javascript必须拒绝。仅用startsWith(http)不够应使用标准 URL 解析并处理大小写、空白、编码和相对路径。图片更复杂。在线图片会产生隐私请求因此 ArkWeb 的onlineImageAccess(false)保持关闭本地相对图片需要把文档目录授权映射为受控资源而不能开启 Web 任意文件访问。导出 HTML 时还要决定嵌入 data URI、复制资源还是保留相对引用每一种都要有大小和路径边界。Bridge 不能被预览内容驱动原生代理与页面同处一个 JavaScript 环境因此必须确保净化后的预览节点无法自动触发原生命令。Bridge 只暴露少量白名单方法文件 URI 永远不传给预览 DOM保存与打印由应用 UI 的明确动作发起。通用onCommand(command, content)仍需在原生侧限制命令枚举、内容长度和当前状态。不能因为 Web 页面随 HAP 打包就跳过校验一旦预览漏洞允许执行页面脚本攻击代码看到的就是同一个 Bridge。原生层必须成为第二道权限边界。更高风险的能力例如打开外部链接、读取本地图片、插件 API 和网络同步应使用更窄的专用协议并附带用户手势或授权上下文。不要不断给现有通用命令添加字符串分支。预览与导出必须共享净化结果导出是最容易被遗漏的第二入口。用户在应用预览中没有看到危险内容并不代表导出的 HTML 安全。如果导出直接使用未净化渲染结果文件在普通浏览器打开时可能获得更宽松的权限。当前sanitizeMarkdown同时供预览、HTML 导出和打印准备使用。独立 HTML 还包含自己的严格 CSP标题经过文本转义页面不加载在线脚本、样式或字体。打印页面则复用已经净化的预览 DOM通过媒体样式隐藏编辑器。共享函数还不够测试必须分别执行三个入口。预览测试检查活动 DOM 没有脚本和副作用导出测试解析返回字符串检查标题、危险 URL和独立 CSP打印测试检查打印模式只保留安全正文。资源耗尽也是安全问题安全不仅是脚本执行。恶意 Markdown 可以包含数十万级嵌套标记、超长链接、巨大 data URI 或使解析器退化的结构导致 ArkWeb 内存激增、页面无响应甚至应用退出。文档大小上限和大文件模式因此也是安全防护。渲染前应限制输入规模大文档关闭实时预览未来插件要限制递归、节点数和输出大小图片 data URI 需要单项上限。打印和导出不能绕过这些保护否则用户虽然能编辑大文件却在点击导出时触发峰值。性能故障的错误信息不应包含完整恶意内容日志也不能记录用户文档。只记录输入大小、阶段、错误类型和匿名诊断即可。安全测试要验证副作用仅检查字符串中没有script不充分。攻击载荷可以通过事件属性、SVG、URL 或解析差异触发。测试应把净化结果放入真实 DOM再检查危险节点、属性、导航和全局副作用。建议载荷集合包括类别示例目标预期脚本标签script作为文本或被移除不执行事件属性onerror、onclick属性不存在危险 URLjavascript:不可导航嵌入上下文iframe/object/embed节点不存在表单form/action不可提交样式style 属性和标签不进入预览网络图片https 图片ArkWeb 不发起在线加载标题注入/title等独立 HTML 标题被转义导出差异预览安全、导出危险三条链路结果一致资源耗尽大 data URI/深层结构受大小或降级策略限制安全依赖升级后必须重新执行这些回归。DOMPurify、markdown-it、ArkWeb 或 CSP 配置变化都可能改变结果。隐私与可观测性的平衡为了排查安全问题应用需要知道预览或导出在哪个阶段失败但不应上传或打印用户 Markdown。诊断可以包含版本、HAP 哈希、文档大小、节点数量、错误类别和发生时间不包含正文、文件路径或 URL 查询参数。如果未来加入崩溃上报和遥测默认应脱敏并允许用户关闭。安全扫描可以在本地执行只返回规则编号和位置范围。鸿蒙 PC 编辑器处理的常常是代码、内部文档和个人笔记隐私边界本身就是产品可信度的一部分。预览安全审查清单所有 Markdown 默认不可信包括本地和工作区文件。markdown-it 禁用原始 HTML插件引入前单独做安全评估。DOMPurify 位于渲染后、DOM 插入前预览与导出共用策略。CSP 使用默认拒绝明确禁止 connect、object、base 和 form。unsafe-inline被记录为折中并有未来收紧路径。ArkWeb 关闭在线图片、文件访问、定位和不必要存储。链接和图片协议经过标准解析与白名单不用字符串猜测。Bridge 只暴露最小方法高风险命令在原生侧再次校验。大文档、data URI 和输出 DOM 有资源上限或降级策略。测试同时覆盖预览、独立 HTML、打印和生产单文件包。诊断不记录正文、敏感 URI 和可识别的文档内容。安全预览不是一个净化函数而是一条从文本输入到系统能力的完整边界。只有渲染器、DOM、浏览器策略、ArkWeb 权限、Bridge 和导出保持一致的默认拒绝鸿蒙 PC 编辑器才能放心打开来源复杂的本地 Markdown。Markdown 插件必须进入同一威胁模型任务列表、脚注、数学公式、Mermaid 和代码高亮会丰富预览也会引入新解析器、DOM 结构、样式和资源。有些插件直接输出 HTML有些运行 JavaScript 修改 DOM有些加载 Web Worker 或字体。安装插件不能只看渲染效果。评估时需要回答输入是否可导致脚本执行输出是否再次经过 DOMPurify是否需要放宽 CSP是否联网是否访问文件是否存在复杂度攻击依赖是否持续维护。必须放宽connect-src或开放unsafe-eval的插件风险很高应优先寻找纯解析、可离线、输出可净化的方案。插件配置作为安全代码审查版本锁定并运行专用载荷。插件失败时预览降级为普通代码块或文本不影响源码编辑和保存。代码高亮的安全与性能边界代码高亮器通常把代码文本解析成带 class 的 span。它不应信任语言名称生成任意 class/属性也不能把代码块内容作为 HTML。语言包数量会增加 HAP 体积和初始化成本自动检测在大代码块上还可能消耗大量 CPU。安全策略可以限定支持语言集合未知语言按纯文本显示输出统一经过净化大文档或大代码块关闭高亮。主题 CSS 使用应用内静态样式不从 CDN 获取。测试包括闭合标签、超长 token、恶意语言名和嵌套标记确认代码仍作为文本显示导出与打印结果一致。本地图片解析需要路径沙箱允许 Markdown 显示相对图片是桌面编辑器的重要能力但打开 ArkWebfileAccess会扩大到未经授权路径。更安全的架构由原生侧在当前文档或工作区授权范围内解析资源请求时校验规范化路径仍位于根目录再通过受控资源 URL、数据流或临时只读映射提供给页面。路径验证要处理..、百分号编码、大小写、符号链接、绝对路径和不同 URI scheme。仅检查字符串前缀不可靠。资源还要限制类型和大小SVG 可能包含脚本或外部引用默认可当作不可信文档进一步净化或禁用。文档切换后旧资源授权应失效不能让新文档继续访问上一目录缓存。导出复制图片时复用同一边界。剪贴板与拖放也是输入通道用户从网页复制内容时剪贴板可能同时包含纯文本和 HTML。源码 Markdown 编辑器默认插入纯文本最可预测若未来支持“粘贴为 Markdown”转换器必须把 HTML 当作不可信输入限制图片下载和链接协议并让用户预览结果。文件拖放可能携带路径、URI 或目录。Web 页面不直接读取拖入文件原生侧根据系统授权创建打开请求。把 HTML 片段直接拖入预览区也不应成为 DOM 注入入口。剪贴板写出同样需要用户动作不允许文档预览自动复制内容。敏感权限和系统提示在鸿蒙 PC 真机验证。外部链接需要用户手势与中间确认当前预览阻止所有链接点击是技术验证期最安全策略。正式产品若开放应只响应真实用户点击解析后显示目标域名和协议危险或未知协议拒绝。本地file:、应用自定义 scheme 和命令链接的权限高于普通https需要独立确认。打开链接最好交给系统默认浏览器不在带原生 Bridge 的同一 ArkWeb 中导航。新窗口也要使用 noopener 语义避免外部页面获得原页面引用。网络访问发生在系统浏览器后编辑器本身仍保持离线边界。链接文案可能伪装域名确认界面应显示解析后的真实目标而不是 Markdown 文本。CSP 违规与安全日志浏览器环境可以提供 CSP 违规信息但 ArkWeb 对报告能力的支持需要验证。开发版本可记录被阻止的资源类型和指令帮助发现构建误配置正式版本不能把完整 URL、文档内容或内联脚本片段上报。若无法使用自动报告生产包测试仍可通过加载页面、监控网络、检查控制台和断言功能来发现违规。CSP 报告是诊断辅助不是安全策略本身。安全日志采用规则编号、页面版本、HAP 哈希和结果码。重复恶意载荷只聚合次数避免攻击者用文档内容污染日志或耗尽磁盘。依赖漏洞响应流程发现 markdown-it、DOMPurify、ArkWeb 或相关插件漏洞时先确认受影响版本和触发条件再制作最小载荷在当前生产 HAP 复现。若影响预览或导出优先临时禁用相关语法/功能并发布修复不等待大版本升级。升级依赖后运行全部安全夹具、生产单文件审计和设备冒烟。补丁若要求放宽 CSP或打开新权限需要更高等级评审。无法立即升级时记录当前配置是否已阻断触发路径并设置明确截止时间。对已导出的 HTML要判断漏洞是否存在于静态内容还是运行库。当前独立 HTML 不带脚本能缩小后续影响这也是避免在导出文件嵌入大型运行时的好处。安全功能也要有可用的失败方式净化器异常、预览超限或本地图片被拒绝时源码编辑必须继续可用。界面显示预览不可用或资源被阻止不清空文档、不尝试未经授权的替代路径。安全策略不能通过崩溃实现拒绝。用户可以查看被阻止资源的原因但不提供“一键永久关闭全部保护”。针对可信工作区的高级选项也应细分能力、明确风险并默认关闭脚本执行和任意 Bridge 调用不应成为普通文档设置。可用的失败方式让用户更少为了完成工作而绕过安全边界。安全边界需要负向能力清单除了列出支持什么还应明确普通 Markdown 永远不能做什么执行脚本、发起网络请求、读取任意本地文件、提交表单、自动打开外部应用、调用保存/打印、写剪贴板和持久化 Web 存储。负向清单让新增功能评审更直接任何需求触碰这些能力都必须单独授权和建模。设备测试可通过网络监控、权限配置和恶意文档验证这些“不发生”的行为。仅观察页面没有弹窗不够后台请求和 Bridge 调用也要断言为零。安全默认与可信工作区用户可能希望在自有文档中使用更多 HTML但“可信工作区”不能成为关闭所有保护的总开关。信任应绑定明确目录、能力和时间允许单独开启本地图片或外部链接不开放脚本与任意原生方法。工作区移动、授权失效或文件来自外部时重新评估。信任状态显示在应用设置或状态区导出仍使用安全默认除非用户明确选择高级格式。任何例外都要可撤销并在升级后保持最小权限。安全审查覆盖生成产物源码配置正确不代表最终 HTML 正确。Vite 单文件插件可能内联新脚本、依赖可能加入动态代码、压缩可能改变 CSP hash。每个候选 HAP 解包或直接检查 rawfile加载生产页面执行恶意夹具并确认 ArkWeb 权限与 Bridge methodList 未扩大。签名保护发布后的 HAP 完整性构建前的依赖和生成过程仍需锁文件、物料清单与 CI 隔离。安全边界从源码一直延伸到用户实际安装的字节。

相关新闻