安全模型
wikitext 通常来自不可信用户。库的目标是:即使源码包含恶意 HTML、URL 或模板,也只输出经过清洗的 React 元素,不执行脚本,不加载未授权的媒体。
库保证什么
不注入 HTML
- 库不使用
dangerouslySetInnerHTML,不把 wikitext 或解析器输出的 HTML 字符串直接交给 React。 - 输出由 HAST 经
hast-util-to-jsx-runtime转换为 React 元素。 - 源码中的危险标签(
script、style、iframe、表单控件、svg、HTML 版math等)默认作为纯文本转义;如果被配置纳入 HTML 解析,或被插件插入 HAST,则整对丢弃并显示可读提示,不执行其中的内容。
清洗顺序固定
- 插件运行在最终清洗之前;插件不能绕过安全阶段。
- 原始解析快照只读;准备阶段在克隆的工作树上操作。
- 最终整理会再次校验
target、rel、图片授权与 URL 协议。
属性与 URL 白名单
- 源码 HTML 只保留
class、title、dir、lang与表格相关属性。 style、id、事件属性、srcdoc不会进入 DOM。href只允许http:、https:、mailto:;src只允许http:、https:。- 校验前会先解码实体,避免
javascript:之类的绕过。 class只经过[A-Za-z0-9_-]安全字符集过滤;colspan/rowspan等有范围限制。
图片授权
- 没有
resolveImage时不会生成<img>。 - 只有解析函数返回并通过 URL 校验的
src会被授权;最终整理会删除未授权图片。 - 授权图片带
loading="lazy"与decoding="async"。 - 库不发起网络请求;图片由浏览器按普通
<img>加载。
模板展开仍按不可信内容处理
expandWikitext只处理宿主提供的模板源码,不执行其中的 HTML 或脚本。- 不内置 Lua,不执行
#invoke。 - 展开结果和模板源码都会经过正常的语义归一化、HAST 转换与最终清洗。
错误隔离
- 每个顶层块由错误边界包裹;一个块渲染失败不影响其他内容。
- 失败时,占位内容显示节点类型与源码,并通过
onRenderError上报。 - 解析、准备错误属于调用阶段,不会由视图错误边界处理。
宿主需要做什么
可信代码
components、semanticComponents、handlers、wikitextPlugins、rehypePlugins、resolveLink、resolveImage 都是宿主代码,属于可信边界。这些代码可以输出白名单之外的 DOM,或把输入插入危险属性;这些内容不再经过库清洗。请像对待普通 React 组件一样审查它们。
路由与媒体地址
解析函数返回的 URL 会经过协议校验,但是否指向正确页面、是否泄露私有资源由宿主决定。接入站内路由或媒体服务时应:
- 使用受信任的映射表或经过验证的页面标题。
- 不要把未经检查的用户输入插入可能执行
javascript:的位置。 - 图片 CDN 域名应写入 CSP 的
img-src。
序列化快照
serializeWikitextRenderDocument 生成普通数据;restoreWikitextRenderDocument 会校验结构版本、数据结构和节点预算,并重新清洗。仍应只恢复来自可信服务端或可信缓存的快照。不要把任意第三方 HAST 直接交给 WikitextView。
策略调整
policy 是安全边界的唯一可调项:
- 放宽
extraTags或减少stripTags会扩大可输出范围。 allowRelativeLinks/allowRelativeImages会改变 URL 校验。allowPluginImages允许 rehype 插件插入图片,仍受协议校验限制。
修改前请确认威胁模型;默认值面向不可信 wikitext。
CSP
库不依赖 eval;内联样式只保留白名单声明(颜色、字体、对齐、宽高、边框、间距等),涉及 url()、expression()、var()、@import、!important 的声明整条丢弃并产生 STYLE_DECLARATION_DROPPED 诊断,因此不会借样式加载远程资源。CSP 禁止 style-src 内联样式时这些声明不生效,但不会执行脚本。如果宿主通过图片解析函数授权远程图片,需要允许对应 img-src;如果使用外部字体或样式,则由宿主自己的 CSP 决定。
已知边界
- 安全模型针对 DOM 与 URL,不阻止用户通过合法外链离开站点。
- 引用、目录、分类等生成结构不携带源码
id,不会与宿主 DOM 冲突。 - 自定义组件可以产生任意 React 输出,这属于宿主信任范围。
- 解析器固定为
wikiparser-node@1.48.1;升级解析器需要重新审查渲染与安全基线。 - 没有内置对清洗结果的审计或 CSP 报告;需要时由宿主接入。
检查清单
- 引入
react-wikitext/styles.css,并给容器设置正确的lang/dir。 - 只为确实需要的页面接入
resolveLink/resolveImage。 - 审查所有组件覆盖与插件,把它们视为可信代码。
- 只恢复可信来源的序列化快照。
- 按站点需求设置 CSP 与图片域名白名单。
- 对不可信输入保持默认策略,不要为了样式放宽清洗。