必须配置CSP响应头Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default,否则Trusted Types不生效;策略名须与createPolicy参数完全一致;innerHTML等危险API赋值需用策略包装TrustedHTML,静态HTML可暂不处理但推荐统一收口。

必须先配 CSP 响应头,否则所有 Trusted Types 代码都不起作用——浏览器根本不会拦截 innerHTML 赋值。
为什么直接加 trustedTypes.createPolicy 没反应
常见错误是只在 JS 里写策略,却没配服务端响应头。浏览器只在收到 Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default 后才启用拦截机制。没这个头,elem.innerHTML = '<script>alert(1)'</script> 照常执行,连控制台都不会报错。
-
trusted-types后面的策略名(如default)必须和createPolicy('default', {})完全一致,大小写敏感,拼错就直接抛TypeError -
require-trusted-types-for 'script'是开关,不是可选项;漏掉它,整个机制等同于不存在 -
<meta http-equiv="Content-Security-Policy">对该指令无效,必须走 HTTP 响应头 - 开发阶段建议先用
Content-Security-Policy-Report-Only收集违规,避免上线后大面积白屏
哪些 innerHTML 赋值必须改,哪些可以不动
不是所有 innerHTML 都要动,关键是看数据来源和上下文:
- 用户输入、URL 参数、API 返回的 HTML 字符串 —— 必须走策略,例如:
el.innerHTML = userInput或el.innerHTML = data.html - 硬编码的静态 HTML(如
el.innerHTML = '<div class="loading">…</div>')可暂不处理,但更推荐统一收口到策略中,便于后续审计 -
textContent不受 Trusted Types 管控,能用就用;它不解析 HTML,天然防 XSS -
insertAdjacentText安全,无需 TrustedHTML;但insertAdjacentHTML和outerHTML同样被拦截,需一并替换
怎么写一个安全又实用的策略函数
别在策略里手写正则过滤 HTML,既不可靠也难维护。正确做法是把净化逻辑移出策略,在外层用 DOMPurify.sanitize() 处理,再包装成 TrustedHTML:
立即学习“前端免费学习笔记(深入)”;
const policy = trustedTypes.createPolicy('html-sanitizer', {
createHTML: (input) => {
// ✅ 净化在策略外做,策略只负责“包装”
return DOMPurify.sanitize(input, { RETURN_TRUSTED_TYPE: true });
}
});
// 使用
el.innerHTML = policy.createHTML(userInput);
- 策略函数必须返回
TrustedHTML实例,不能返回字符串,否则赋值失败 - 策略对象字面量里不能引用闭包变量或外部函数,否则在某些浏览器中会创建失败
- 避免命名策略为
default,除非你真打算让它处理所有 HTML 场景;按用途拆分更可控,比如comment-html、email-html - 若策略函数抛异常(如 DOMPurify 初始化失败),
innerHTML赋值直接中断,页面可能卡住——务必加 try/catch 并 fallback 到textContent
legacy 项目中最容易漏掉的高危点
重构时盯着 innerHTML 很容易忽略其他等效入口:
-
document.write()和document.writeln()同样被拦截,且无法用策略绕过,必须彻底删除或重写 -
location.assign(url)若传入javascript:伪协议字符串,会被拦;必须用trustedTypes.createPolicy(...).createScriptURL()包装 -
DOMParser.parseFromString(html, 'text/html')返回的Document中含脚本时,也会触发 Trusted Types 校验 -
<iframe srcdoc="...">和<object data="...">的属性值同样需TrustedHTML,但常被遗漏 - 框架内部调用(如 React 的
dangerouslySetInnerHTML)是否兼容 Trusted Types,得查对应版本文档;旧版可能逃逸防护
最麻烦的不是写策略,而是定位所有 sink —— 建议用 grep -r "innerHTML\|insertAdjacentHTML\|document\.write" src/ 全局扫,再结合 CSP Report-Only 模式验证覆盖度。



















