trusted types 不能彻底重构字符串拼接逻辑,但能强制将高危 dom 写入点切换为类型受控对象;需启用 csp 响应头(trusted-types default; require-trusted-types-for 'script')、全覆盖 sink(innerhtml、insertadjacenthtml、document.write、eval 等)、定义最小必要策略(禁用正则过滤、优先用 textcontent)、并适配框架与第三方库。

Trusted Types 不能“彻底重构”字符串拼接逻辑,但它能强制将所有高危 DOM 写入点从 string 切换为类型受控的 TrustedHTML、TrustedScript 等对象——前提是项目已启用 CSP 强制策略,并覆盖全部 sink。所谓“重构”,本质是把运行时信任委托从开发者手动拼接,转为浏览器级类型校验。
第一步:确认浏览器兼容性与 CSP 基础配置
全链路生效的前提是服务端返回正确的 HTTP 头,仅前端加 JS 策略无效:
-
必须使用 HTTP 响应头,
<meta http-equiv="Content-Security-Policy">不支持require-trusted-types-for - 生产环境最小可行头:
Content-Security-Policy: trusted-types default; require-trusted-types-for 'script'; default-src 'self'; -
default是策略名占位符,若项目用自定义名(如dom-sanitizer),CSP 中必须显式列出,否则浏览器回退到宽松模式 - 开发阶段可用
Content-Security-Policy-Report-Only先捕获违规,避免上线即阻断
第二步:识别并替换全部高危 sink 调用点
不能只改 innerHTML。遗留项目中常见被忽略的逃逸入口包括:
-
el.insertAdjacentHTML('beforeend', unsafe)—— 同样受控,需统一走策略 -
document.write(unsafe)和document.writeln()—— 已淘汰但老代码仍存 -
location.href = 'javascript:alert(1)'—— 需用createURL策略包装 -
eval('...')、setTimeout('...', 100)、setInterval('...', 100)—— 字符串形式执行必须禁用或重写为函数形式 -
el.setAttribute('onerror', '...')—— 部分浏览器已拦截,但不可依赖;推荐改用el.onerror = handler
第三步:定义最小必要策略,拒绝“万能 HTML 构造器”
策略不是过滤器,而是可信内容的“出口闸门”。每个策略应职责单一、上下文明确:
- 不要在
createHTML里做白名单过滤或正则清洗 —— 易绕过且性能差 - 纯文本展示优先用
textContent,完全绕过 Trusted Types 限制 - 必须插 HTML 时,先用 DOMPurify 在策略外净化,再由策略包装:
createHTML: (input) => DOMPurify.sanitize(input) - 对模板场景,可封装预编译策略:
createHTML: (tpl, data) => Mustache.render(tpl, data)(确保Mustache输出已净化) - 禁止策略内调用
eval、new Function或拼接后直接return string
第四步:处理框架与第三方库集成
React/Vue/Angular 等现代框架大多已适配 Trusted Types,但旧版本或自定义渲染逻辑可能逃逸:
- 检查框架文档是否声明支持
require-trusted-types-for,如 React 18.3+、Vue 3.4+ 默认兼容 - 禁用框架中允许传入原始 HTML 的 API(如 Vue 的
v-html、React 的dangerouslySetInnerHTML),改用受控组件或策略包装 - 第三方 UI 库(如 Ant Design、Element Plus)若内部调用
innerHTML,需确认其是否导出策略接口,或通过 wrapper 统一拦截 - Web Components 中
shadowRoot.innerHTML在 Safari 17.4+ / Firefox 148+ 已受控,但旧版需降级处理
不复杂但容易忽略。










