trusted types 必须配合 csp 响应头 content-security-policy: require-trusted-types-for 'script'; trusted-types default 才生效,仅 js 端创建策略无防护效果;未配该头时 innerhtml = str 静默执行,不报错也不拦截;meta 标签无法设置该指令,必须通过 http 响应头配置。

Trusted Types 不是加个 JS 就能修好 innerHTML 的补丁,它必须配合 CSP 响应头生效;没配 Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default,所有策略代码都等于白写。
为什么直接改 innerHTML = str 会报错却没防护效果
浏览器只在收到 HTTP 响应头后才启用 Trusted Types 拦截机制。即使你在 JS 里调用了 trustedTypes.createPolicy('default', {...}),只要服务端没返回对应 CSP 头,elem.innerHTML = '<img onerror="alert(1)">' 依然静默执行,不报错也不拦截。
- 开发阶段可用
Content-Security-Policy-Report-Only先收集违规日志,避免上线即崩 -
meta标签无法设置require-trusted-types-for,必须走 HTTP 响应头(Nginx/Apache/CDN 都要配) - 策略名必须是
default—— 浏览器默认回退策略只认这个名字,写成myPolicy会导致创建失败并抛TypeError
哪些 innerHTML 替代写法其实仍危险
不是把 innerHTML 换成 textContent 就万事大吉。很多 legacy 代码用“伪安全”方式绕过检查,结果照样被拦截或失效:
-
elem.outerHTML = htmlString和elem.insertAdjacentHTML('beforeend', htmlString)同样受控,必须同样走 TrustedHTML -
DOMParser.parseFromString(html, 'text/html')返回的Document若含脚本标签,也会触发 Trusted Types 拦截 - 用
el.setAttribute('innerHTML', ...)是无效操作——这个属性根本不存在,不会触发拦截,但也不会生效 -
document.write()和document.writeln()已被严格限制,连字符串拼接都不行
如何为不同场景设计最小权限策略
别用一个 createHTML 函数处理所有 HTML:它容易变成“信任委托”,反而埋下绕过漏洞。
- 纯文本渲染 → 直接用
textContent,彻底避开 HTML 解析 - 富文本内容 → 交给
DOMPurify.sanitize()预处理,再由策略包装:createHTML: html => DOMPurify.sanitize(html) - 模板字符串插值 → 把变量提前转义,再拼进模板:
createHTML: () => `<div>${escape(userInput)}</div>`,不要在策略里做运行时解析 - 动态组件挂载 → 用
customElements.define()+shadowRoot.innerHTML,注意部分旧版 Chrome 对 shadow DOM 的 sink 拦截不完整
重构时最容易被忽略的三个点
很多团队卡在最后一步:不是策略写错了,而是漏掉了协同层。
- 第三方库(如旧版 jQuery、某些 UI 组件)内部仍用
innerHTML,必须升级或打 patch,否则策略一开就崩 -
<iframe srcdoc=""></iframe>和<object data=""></object>的属性值也需TrustedHTML,常被遗漏 -
location.assign(url)若传字符串会被拦,必须用trustedTypes.createPolicy('default').createURL()包装
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











