trusted types 是需服务端、策略层、调用层协同的强制校验机制,须配置 csp 响应头(require-trusted-types-for 'script'; trusted-types default)才能生效,所有高危 dom 操作必须使用 trustedhtml 等实例。

Trusted Types 不是加个 JS 库就能生效的补丁,它是一套需要服务端、策略层、调用层协同的强制校验机制。重构 legacy 项目的关键,是让所有高危 DOM 操作(如 innerHTML、insertAdjacentHTML、document.write 等)不再接收原始字符串,而是只接受由可信策略生成的 TrustedHTML 或 TrustedScriptURL 实例。
必须先配置 CSP 响应头才能启动防护
浏览器只在收到 HTTP 头后才拦截非法赋值,JS 里创建策略本身不产生任何防护效果。
- 生产环境必需头:
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default; -
default是强制要求的策略名——如果策略名不匹配,trustedTypes.createPolicy("default", {...})创建失败时会直接抛错,而非静默降级 -
require-trusted-types-for 'script'是开关:开启后,elem.innerHTML = "<img src="x" onerror="alert(1)">"这类写法立即报TypeError - 不支持
<meta http-equiv="Content-Security-Policy">设置该指令,必须走 HTTP 响应头 - 开发阶段可用
Content-Security-Policy-Report-Only先捕获违规,避免上线即崩
识别并替换所有危险 DOM 插入点
legacy 代码中常见被忽略的高危操作,不止 innerHTML:
-
outerHTML、insertAdjacentHTML、document.write、document.writeln -
DOMParser.parseFromString(html, "text/html")返回的 Document 中若含脚本,也受控 -
<iframe srcdoc="..."></iframe>和<object data="..."></object>的属性值同样需TrustedHTML -
location.assign(url)若传字符串会被拦,必须传TrustedURL实例 -
elem.setAttribute("onclick", "...")属于内联事件,已由require-trusted-types-for 'script'覆盖,无需额外处理
为不同场景设计最小权限策略
避免用一个“万能策略”处理所有 HTML——这违背 Trusted Types 的设计初衷,也增加误用风险。
- 纯内容渲染(如评论、文章正文):策略只允许白名单标签(
p、strong、ul等),剥离 script/style/script 标签和事件属性 - 富文本编辑器输出:可启用
createHTML+ DOMPurify 集成,但需确保净化后仍返回TrustedHTML - 模板拼接(如 Handlebars 渲染结果):策略应仅封装已知安全的模板输出,禁止接受用户输入直传
- 第三方库集成(如 jQuery):利用其内置适配能力,
jQuery(getHtmlWrapper(...))可自动识别TrustedHTML;未适配的库需包装一层策略代理
渐进式迁移与兼容性保障
全量重写不现实,优先保护高风险模块,同时保持旧逻辑可运行。
- 对已有函数做“策略包裹”:例如把
renderUserContent(html)改为renderUserContent(trustedTypes.default.createHTML(html)) - 保留
textContent作为安全兜底:对纯文本场景,elem.textContent = userInput无需 Trusted Types,且天然防 XSS - 不支持 Trusted Types 的老浏览器(如 IE、旧版 Safari)不会报错,但也不执行校验——需配合其他防御手段(如服务端过滤、CSP 兜底)
- 使用
trustedTypes.isTrustedHTML(value)在运行时做类型检查,辅助调试和灰度验证










