createPolicy 必须配合 CSP 响应头才生效:未配置 Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default 时,trustedTypes.createPolicy() 调用完全无效,浏览器既不拦截也不报错;策略名必须与 CSP 中声明的完全一致(如 default),且 createHTML 只能返回净化后的字符串,不可手动构造 TrustedHTML;企业级安全要求按场景拆分策略名并显式声明,否则审计不通过;所有 HTML 注入类 API(如 insertAdjacentHTML、location.assign 等)均受控,需统一使用对应策略封装。

createPolicy 必须配合 CSP 响应头才生效
没配 Content-Security-Policy HTTP 响应头,trustedTypes.createPolicy() 调用直接无效——浏览器既不拦截 innerHTML,也不校验策略名,连控制台都不会报错。这不是“功能没开”,而是机制压根没启动。
生产环境必需的响应头是:Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default。注意两点:
-
default是硬性策略名:JS 里调用trustedTypes.createPolicy("default", {...})才能匹配;写成"html"或"myPolicy"但 CSP 没同步更新,会立即抛TypeError: Policy name mismatch -
<meta http-equiv="Content-Security-Policy">对require-trusted-types-for完全无效,必须走服务端 HTTP 响应头
createHTML 函数只能返回字符串,不能手动构造 TrustedHTML
createHTML 不是过滤器,也不是工厂方法;它只是把输入“封装”进可信类型管道的入口。浏览器内部会自动把返回的字符串包装成 TrustedHTML 实例——你不能、也不该手动 new TrustedHTML(...),那会直接报错。
正确做法是让 createHTML 返回一个已净化的字符串:
立即学习“前端免费学习笔记(深入)”;
- ✅ 推荐:
createHTML: (raw) => DOMPurify.sanitize(raw, { RETURN_TRUSTED_TYPE: true })(需 DOMPurify ≥ 3.0) - ✅ 可接受:
createHTML: (raw) => raw.replace(/, '<').replace(/>/g, '>')(仅限纯文本场景,禁用所有标签) - ❌ 危险:
createHTML: (raw) => raw(等于放行全部 HTML,审计必挂) - ❌ 报错:
createHTML: (raw) => new TrustedHTML(raw)(浏览器不暴露该构造函数)
别用一个 default 策略包打天下
企业级安全审查(如 SOC2、ISO 27001)会静态扫描策略实现。如果所有 HTML 都走同一个 default 策略,且里面只做简单转义或无条件返回,会被标记为“弱策略”并拒绝过审。
真实项目应按数据来源和渲染意图拆分策略名,并在 CSP 头中显式声明:
- 模板引擎输出 →
trusted-types handlebars markdown,策略里集成marked并移除script、onerror等危险属性 - 用户富文本 →
trusted-types user-content,强制走 DOMPurify 白名单(仅允许b、i、p) - 跳转 URL → 单独定义
createScriptURL,禁止javascript:协议和内联脚本
策略名不匹配 CSP 白名单时不会降级,而是整个页面的 innerHTML 调用直接失败,表现为白屏或 JS 报错中断。
容易被忽略的 sink 场景远不止 innerHTML
只改 element.innerHTML = str 是远远不够的。启用 Trusted Types 后,以下操作同样会被拦截,且漏掉任一都会导致功能异常或绕过防护:
-
element.insertAdjacentHTML('beforeend', str)→ 必须用policy.createHTML(str) -
location.assign(url)→ 必须用policy.createScriptURL(url),否则跳转会失败 -
document.write(str)和document.writeln(str)→ 已被彻底禁用,必须重写为innerHTML+ 策略封装 -
DOMParser.parseFromString(html, 'text/html')返回的 Document 若含脚本,也受控;需确保传入的是policy.createHTML(...)结果 -
<iframe srcdoc="...">和<object data="...">的属性值,同样需要TrustedHTML
第三方库(如旧版 Bootstrap 插件、某些图表库)若内部直写 innerHTML,必须用代理 wrapper 封装其 DOM 操作路径——框架不会自动适配,得你手动兜底。



















