
angular 在插值(`{{ }}`)中自动对内容进行 html 实体编码,将 `<script>` 等标签转义为纯文本(如 `<script>`),既不执行脚本,也不依赖 `domsanitizer` 进行主动过滤——这是编译时的默认安全机制。</script>
在 Angular 中,插值绑定(如 <div>{{ test }}</div>)不会将字符串解析为 HTML,而是将其作为纯文本插入 DOM。这意味着即使 test = '<script>alert("xss")</script>',Angular 也会自动将 <、>、" 等字符转换为对应的 HTML 实体(例如 <script>alert("xss")</script>),最终在页面上显示为可见的源码文本,而非可执行的脚本。
这与 [innerHTML] 的行为有本质区别:
- ✅ 插值 {{ }}:始终进行上下文感知的文本转义(context-aware escaping),属于“输出编码”(output encoding),是编译器层面的默认防护,不经过 DomSanitizer;
- ⚠️ [innerHTML]:明确要求渲染 HTML,因此 Angular 会调用 DomSanitizer.sanitize(SecurityContext.HTML, value),主动移除 <script>、onerror、javascript: 等危险内容。
因此,回答你的两个问题:
- 插值不“由 DomSanitizer 消毒”——它根本没进入 sanitizer 流程。Angular 文档中提到的“sanitizes and escapes untrusted values”在插值场景下,实际指自动 HTML 编码(escaping),而非 sanitizer 的“清理(sanitization)”。这是更底层、更严格的安全策略:宁可显示为文本,也不冒险解析。
- 脚本不执行,是因为它从未被当作 HTML 解析——DOM 中插入的是已编码的字符串节点,浏览器识别不到 <script> 标签,自然不会触发 JS 解析与执行。
✅ 正确示例(安全,默认行为):
<!-- component.ts -->
test = '<script>alert("xss")</script>';
<!-- template.html -->
<div>{{ test }}</div>
<!-- 渲染结果(纯文本): -->
<!-- <script>alert("xss")</script> -->❌ 错误尝试(危险!禁止):
<!-- 绝对不要这样写 --> <div [innerHTML]="test"></div> <!-- 若 test 含恶意脚本,可能被 sanitizer 拦截,但仍有风险 --> <!-- 若强行绕过 sanitizer(极度危险) --> <div [innerHTML]="sanitizer.bypassSecurityTrustHtml(test)"></div>
⚠️ 注意事项:
- 不要为插值内容手动调用 bypassSecurityTrustHtml() —— 它仅适用于 [innerHTML] 等特定绑定,对 {{ }} 无效且无意义;
- 如需动态渲染可信 HTML,请显式使用 [innerHTML] + DomSanitizer,并确保数据来源绝对可靠(如 CMS 白名单内容);
- 始终遵循“最小权限”原则:优先使用插值显示文本,仅在必要时启用 HTML 渲染,并配合严格的内容校验与服务端净化。
总之,Angular 插值的安全性源于“不解析、只转义”的设计哲学——它不是“忘了消毒”,而是以更保守的方式从根本上杜绝 XSS 执行路径。










