Tests
- DOMParser-parseFromString-regression.html (live test) (source)
- DOMParser-parseFromString.html (live test) (source)
- DedicatedWorker-block-eval-function-constructor.html (live test) (source)
- DedicatedWorker-constructor-from-DedicatedWorker.html (live test) (source)
- DedicatedWorker-constructor-from-SharedWorker.html (live test) (source)
- DedicatedWorker-constructor.https.html (live test) (source)
- DedicatedWorker-eval.html (live test) (source)
- DedicatedWorker-importScripts.html (live test) (source)
- DedicatedWorker-setTimeout-setInterval.html (live test) (source)
- Document-execCommand.html (live test) (source)
- Document-write-appending-line-feed.html (live test) (source)
- Document-write-exception-order.xhtml (live test) (source)
- Document-write.html (live test) (source)
- Element-insertAdjacentHTML.html (live test) (source)
- Element-outerHTML.html (live test) (source)
- Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-TT-realm.html (live test) (source)
- Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-non-TT-realm.html (live test) (source)
- Element-setAttribute.html (live test) (source)
- Element-setAttributeNS.html (live test) (source)
- Element-toggleAttribute.html (live test) (source)
- GlobalEventHandlers-onclick.html (live test) (source)
- HTMLElement-generic.html (live test) (source)
- HTMLScriptElement-in-xhtml-document.tentative.https.xhtml (live test) (source)
- HTMLScriptElement-internal-slot.html (live test) (source)
- Node-multiple-arguments-tt-enforced.html (live test) (source)
- Node-multiple-arguments.html (live test) (source)
- Range-createContextualFragment.html (live test) (source)
- SVGScriptElement-internal-slot.html (live test) (source)
- ServiceWorker-block-eval-function-constructor.https.html (live test) (source)
- ServiceWorker-eval.https.html (live test) (source)
- ServiceWorker-importScripts.https.html (live test) (source)
- ServiceWorkerContainer-register-from-DedicatedWorker.https.html (live test) (source)
- ServiceWorkerContainer-register-from-ServiceWorker.https.html (live test) (source)
- ServiceWorkerContainer-register-from-SharedWorker.https.html (live test) (source)
- ServiceWorkerContainer-register.https.html (live test) (source)
- SharedWorker-block-eval-function-constructor.html (live test) (source)
- SharedWorker-constructor.https.html (live test) (source)
- SharedWorker-eval.html (live test) (source)
- SharedWorker-importScripts.html (live test) (source)
- SharedWorker-setTimeout-setInterval.html (live test) (source)
- TrustedType-AttributeNodes.html (live test) (source)
- TrustedTypePolicy-CSP-no-name.html (live test) (source)
- TrustedTypePolicy-CSP-wildcard.html (live test) (source)
- TrustedTypePolicy-createXXX.html (live test) (source)
- TrustedTypePolicyFactory-constants.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-createXYZTests.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-cspTests-noNamesGiven.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-cspTests-none-none-name.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-cspTests-none-none.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-cspTests-none.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-cspTests-wildcard.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-cspTests.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-non-tt-policy-name.html (live test) (source)
- TrustedTypePolicyFactory-createPolicy-unenforced.html (live test) (source)
- TrustedTypePolicyFactory-defaultPolicy.html (live test) (source)
- TrustedTypePolicyFactory-getAttributeType-namespace.html (live test) (source)
- TrustedTypePolicyFactory-getAttributeType-svg.html (live test) (source)
- TrustedTypePolicyFactory-getAttributeType.html (live test) (source)
- TrustedTypePolicyFactory-isXXX.html (live test) (source)
- Window-TrustedTypes.html (live test) (source)
- Window-block-eval-function-constructor.html (live test) (source)
- Window-setTimeout-setInterval.html (live test) (source)
- block-Document-execCommand.html (live test) (source)
- block-string-assignment-to-DOMParser-parseFromString.html (live test) (source)
- block-string-assignment-to-DedicatedWorker-setTimeout-setInterval.html (live test) (source)
- block-string-assignment-to-Document-parseHTMLUnsafe.html (live test) (source)
- block-string-assignment-to-Document-write.html (live test) (source)
- block-string-assignment-to-Element-insertAdjacentHTML.html (live test) (source)
- block-string-assignment-to-Element-outerHTML.html (live test) (source)
- block-string-assignment-to-Element-setAttribute.html (live test) (source)
- block-string-assignment-to-Element-setAttributeNS.html (live test) (source)
- block-string-assignment-to-Element-setHTMLUnsafe.html (live test) (source)
- block-string-assignment-to-HTMLElement-generic.html (live test) (source)
- block-string-assignment-to-HTMLIFrameElement-srcdoc.html (live test) (source)
- block-string-assignment-to-Range-createContextualFragment.html (live test) (source)
- block-string-assignment-to-ShadowRoot-innerHTML.html (live test) (source)
- block-string-assignment-to-ShadowRoot-setHTMLUnsafe.html (live test) (source)
- block-string-assignment-to-SharedWorker-setTimeout-setInterval.html (live test) (source)
- block-string-assignment-to-Window-setTimeout-setInterval.html (live test) (source)
- block-string-assignment-to-attribute-via-attribute-node.html (live test) (source)
- block-string-assignment-to-text-and-url-sinks.html (live test) (source)
- block-text-node-insertion-into-script-element.html (live test) (source)
- block-text-node-insertion-into-svg-script-element.html (live test) (source)
- csp-block-eval.html (live test) (source)
- default-policy-callback-arguments.html (live test) (source)
- default-policy-report-only.html (live test) (source)
- default-policy.html (live test) (source)
- empty-default-policy-report-only.html (live test) (source)
- empty-default-policy.html (live test) (source)
- eval-csp-no-tt.html (live test) (source)
- eval-csp-tt-default-policy-mutate.html (live test) (source)
- eval-csp-tt-default-policy.html (live test) (source)
- eval-csp-tt-no-default-policy.html (live test) (source)
- eval-function-constructor-untrusted-arguments-and-applying-default-policy.html (live test) (source)
- eval-function-constructor-untrusted-arguments-and-default-policy-throwing.html (live test) (source)
- eval-function-constructor.html (live test) (source)
- eval-no-csp-no-tt-default-policy.html (live test) (source)
- eval-no-csp-no-tt.html (live test) (source)
- eval-with-permissive-csp.html (live test) (source)
- get-trusted-types-compliant-attribute-value.html (live test) (source)
- idlharness.window.js (live test) (source)
- inheriting-csp-for-local-schemes.html (live test) (source)
- legacy-trusted-script-urls.html (live test) (source)
- legacy-trusted-scripts.html (live test) (source)
- modify-attributes-in-callback.html (live test) (source)
- no-require-trusted-types-for-report-only.html (live test) (source)
- no-require-trusted-types-for.html (live test) (source)
- require-trusted-types-for-TypeError-belongs-to-the-global-object-realm.html (live test) (source)
- require-trusted-types-for-report-only.html (live test) (source)
- require-trusted-types-for.html (live test) (source)
- script-enforcement-001-outerHTML.xhtml (live test) (source)
- script-enforcement-001.html (live test) (source)
- script-enforcement-002-outerHTML.xhtml (live test) (source)
- script-enforcement-002.html (live test) (source)
- script-enforcement-003.html (live test) (source)
- script-enforcement-004.html (live test) (source)
- script-enforcement-005.html (live test) (source)
- script-enforcement-006.html (live test) (source)
- script-enforcement-007.html (live test) (source)
- script-enforcement-008.https.html (live test) (source)
- script-enforcement-009.https.html (live test) (source)
- script-enforcement-010.html (live test) (source)
- script-enforcement-011.html (live test) (source)
- set-attributes-no-require-trusted-types.html (live test) (source)
- set-attributes-require-trusted-types-default-policy.html (live test) (source)
- set-attributes-require-trusted-types-no-default-policy.html (live test) (source)
- should-sink-type-mismatch-violation-be-blocked-by-csp-001.html (live test) (source)
- should-sink-type-mismatch-violation-be-blocked-by-csp-002-worker.html (live test) (source)
- should-sink-type-mismatch-violation-be-blocked-by-csp-003.html (live test) (source)
- should-trusted-type-policy-creation-be-blocked-by-csp-001.html (live test) (source)
- should-trusted-type-policy-creation-be-blocked-by-csp-002.html (live test) (source)
- should-trusted-type-policy-creation-be-blocked-by-csp-003.html (live test) (source)
- should-trusted-type-policy-creation-be-blocked-by-csp-004-worker.html (live test) (source)
- should-trusted-type-policy-creation-be-blocked-by-csp-005.html (live test) (source)
- trusted-types-createHTMLDocument.html (live test) (source)
- trusted-types-duplicate-names-list-report-only.html (live test) (source)
- trusted-types-duplicate-names-list.html (live test) (source)
- trusted-types-duplicate-names-without-enforcement.html (live test) (source)
- trusted-types-duplicate-names.html (live test) (source)
- trusted-types-eval-reporting-no-unsafe-eval.html (live test) (source)
- trusted-types-eval-reporting-report-only.html (live test) (source)
- trusted-types-event-handlers.html (live test) (source)
- trusted-types-navigation.html (live test) (source)
- trusted-types-report-only.html (live test) (source)
- trusted-types-reporting-check-report-DedicatedWorker-create-policy.html (live test) (source)
- trusted-types-reporting-check-report-DedicatedWorker-sink-mismatch.html (live test) (source)
- trusted-types-reporting-check-report-Window-create-policy.html (live test) (source)
- trusted-types-reporting-check-report-Window-sink-mismatch.html (live test) (source)
- trusted-types-reporting-clipping-of-sample.html (live test) (source)
- trusted-types-reporting-for-DOMParser-parseFromString.html (live test) (source)
- trusted-types-reporting-for-DedicatedWorker-DedicatedWorker-constructor.html (live test) (source)
- trusted-types-reporting-for-DedicatedWorker-ServiceWorkerContainer-register.https.html (live test) (source)
- trusted-types-reporting-for-DedicatedWorker-eval.html (live test) (source)
- trusted-types-reporting-for-DedicatedWorker-function-constructor.html (live test) (source)
- trusted-types-reporting-for-DedicatedWorker-importScripts.html (live test) (source)
- trusted-types-reporting-for-DedicatedWorker-setTimeout-setInterval.html (live test) (source)
- trusted-types-reporting-for-Document-execCommand.html (live test) (source)
- trusted-types-reporting-for-Document-parseHTMLUnsafe.html (live test) (source)
- trusted-types-reporting-for-Document-write.html (live test) (source)
- trusted-types-reporting-for-Element-innerHTML.html (live test) (source)
- trusted-types-reporting-for-Element-insertAdjacentHTML.html (live test) (source)
- trusted-types-reporting-for-Element-outerHTML.html (live test) (source)
- trusted-types-reporting-for-Element-setAttribute.html (live test) (source)
- trusted-types-reporting-for-Element-setHTMLUnsafe.html (live test) (source)
- trusted-types-reporting-for-HTMLIFrameElement-srcdoc.html (live test) (source)
- trusted-types-reporting-for-HTMLScriptElement-children-change.html (live test) (source)
- trusted-types-reporting-for-HTMLScriptElement-innerHTML.html (live test) (source)
- trusted-types-reporting-for-HTMLScriptElement.html (live test) (source)
- trusted-types-reporting-for-Range-createContextualFragment.html (live test) (source)
- trusted-types-reporting-for-SVGScriptElement-children-change.html (live test) (source)
- trusted-types-reporting-for-SVGScriptElement-innerHTML.html (live test) (source)
- trusted-types-reporting-for-ServiceWorker-ServiceWorkerContainer-register.https.html (live test) (source)
- trusted-types-reporting-for-ServiceWorker-eval.https.html (live test) (source)
- trusted-types-reporting-for-ServiceWorker-function-constructor.https.html (live test) (source)
- trusted-types-reporting-for-ServiceWorker-importScripts.https.html (live test) (source)
- trusted-types-reporting-for-ServiceWorker-setTimeout-setInterval.https.html (live test) (source)
- trusted-types-reporting-for-ShadowRoot-innerHTML.html (live test) (source)
- trusted-types-reporting-for-ShadowRoot-setHTMLUnsafe.html (live test) (source)
- trusted-types-reporting-for-SharedWorker-DedicatedWorker-constructor.html (live test) (source)
- trusted-types-reporting-for-SharedWorker-ServiceWorkerContainer-register.https.html (live test) (source)
- trusted-types-reporting-for-SharedWorker-eval.html (live test) (source)
- trusted-types-reporting-for-SharedWorker-function-constructor.html (live test) (source)
- trusted-types-reporting-for-SharedWorker-importScripts.html (live test) (source)
- trusted-types-reporting-for-SharedWorker-setTimeout-setInterval.html (live test) (source)
- trusted-types-reporting-for-Window-DedicatedWorker-constructor.html (live test) (source)
- trusted-types-reporting-for-Window-ServiceWorkerContainer-register.https.html (live test) (source)
- trusted-types-reporting-for-Window-SharedWorker-constructor.html (live test) (source)
- trusted-types-reporting-for-Window-eval.html (live test) (source)
- trusted-types-reporting-for-Window-function-constructor.html (live test) (source)
- trusted-types-reporting-for-Window-setTimeout-setInterval.html (live test) (source)
- trusted-types-reporting.html (live test) (source)
- trusted-types-sandbox-allow-scripts.html (live test) (source)
- trusted-types-sandbox-no-allow-scripts.html (live test) (source)
- trusted-types-source-file-path.html (live test) (source)
- trusted-types-svg-script-set-href.html (live test) (source)
- trusted-types-tojson.html (live test) (source)
- tt-block-eval.html (live test) (source)
1. 简介
本节为非规范性内容。
当 Web 应用程序 从攻击者控制的来源(例如 文档 URL 参数或 postMessage 通道)获取值,并将该值 未经适当净化便传递给某个 注入接收点——即各种具有 强大能力的 Web API 函数时,就会出现某些类型的漏洞。
传统上,这类问题很难防止。
应用程序通常会使用攻击者控制的
值调用这些注入接收点,而作者却没有意识到这一点,因为调用注入接收点时
并不清楚输入是否由攻击者控制。
由于 JavaScript 的动态特性,也很难确定
给定程序中是否不存在这种模式。在人工代码审查和自动代码分析期间,
这种问题经常被遗漏。例如,
如果 aString 包含不可信数据,则 foo[bar] = aString 是一条
可能触发漏洞的语句,具体取决于
foo 和 bar 的值。
本文档重点关注防止基于 DOM 的跨站脚本攻击,
这种攻击发生在攻击者控制的数据到达
§ 2.1.1 DOM XSS 注入接收点时,因为这最终会导致执行
由攻击者控制的
脚本载荷。DOM XSS 在
Web 应用程序中很常见,因为存在 60 多种不同的
注入接收点(例如 Element.innerHTML 或 Location.href 设置器)。
本文档定义了 可信类型——一种允许应用程序 锁定注入接收点 使其仅接受不可伪造的、带类型的值 而不是字符串的 API。这些值反过来只能由 应用程序定义的策略创建,从而允许 作者定义规则 来保护危险 API,将攻击面缩小到 Web 应用程序代码库中少量、隔离的部分,这些部分更容易进行防护、 监控和审查。
1.1. 目标
-
尽量降低在 使用不可信数据调用强大的 Web API 时发生客户端漏洞的可能性——例如, 尽量降低 DOM XSS 的可能性。
-
鼓励采用一种设计,使安全决策 封装在应用程序的一小部分中。
-
缩小复杂 Web 应用程序 代码库的安全审查范围。
-
允许以不影响可用性的方式检测漏洞,类似于常规 编程错误被检测并呈现给开发者的方式,同时借助 动态和静态分析工具。
1.2. 非目标
-
防止或缓解注入服务器端生成的 标记所造成的结果,尤其是反射到 文档中运行的脚本主体内的内容。为应对服务器端 XSS 向量,我们建议使用现有 解决方案,例如模板系统或 CSP script-src。
-
处理资源限制,例如防止数据外泄,或 通过 [Fetch] 连接到外部来源。
-
控制子资源加载。可信类型旨在允许作者 控制能够为当前文档执行脚本的资源加载,但不控制 其他子资源。
-
防止跨源 JavaScript 执行(例如,可信类型 不会防止通过
data:URL 加载包含 JavaScript 代码的新文档)。 -
防止 Web 应用程序 JavaScript 代码的恶意作者 绕过这些限制;试图防范 恶意作者会导致设计过于复杂且 不切实际。
1.3. 用例
-
某位作者维护一个使用框架编写的复杂 Web 应用程序, 该框架使用安全的模板系统来生成 UI 组件。该应用程序还依赖执行辅助任务 (例如分析、性能监控)的第三方客户端 库。为确保这些组件都不会引入 DOM XSS 漏洞,作者在 模板库中定义一个可信类型策略,并对 § 2.1.1 DOM XSS 注入接收点启用强制执行。
-
某个网站使用 § 2.1.1 DOM XSS 注入接收点。该 网站开发者向其中添加可信 类型,并通过 Content-Security-Policy-Report-Only 标头字段监控违规。 通过重构代码以仅使用安全 方法来逐步修复违规。之后,不再有 § 2.1.1 DOM XSS 注入接收点 被调用。 因此,也就不再需要可信类型。开发者关闭 仅报告模式,并通过 trusted-types 和 require-trusted-types-for 指令禁用可信类型策略。 在重构期间,网站的功能从未受损。
-
一个大型团队维护复杂的客户端应用程序。 他们创建若干满足应用程序安全 要求的可信类型策略。团队将策略 实现以及使用这些策略的安全抽象集中到少量 经过严格审查的文件中,并要求对 影响这些文件的提交进行额外批准。
为了影响注入接收点而必须创建可信值, 再加上对影响策略 代码的更严格变更审查,会促使开发者使用安全抽象,而不是编写临时的 字符串组合代码来与 § 2.1.1 DOM XSS 注入接收点交互。
在考虑 DOM XSS 风险时,安全审计人员发现 攻击面很小;他们专注于少量 构造 CSP 标头并提供安全抽象的代码,而忽略 大部分客户端应用程序代码。
-
现有 Web 应用程序主要使用 XSS 安全的 模式与 DOM 交互(即不使用 § 2.1.1 DOM XSS 注入 接收点)。不过,在少数位置, 它仍会采用有风险的模式,例如使用 JSONP 加载额外脚本、调用
innerHTML或eval。审查发现这些位置不会导致 XSS(例如因为 用户控制的数据并不是这些接收点输入的一部分),但 很难将应用程序迁移到不使用这些模式。
因此,无法在该应用程序上强制执行 CSP(除非采用 使用
'unsafe-eval' 'unsafe-inline'的不安全版本)。此外, 某些存在 DOM XSS 缺陷的代码可能没有被纳入审查, 或者未来可能会引入此类代码。为解决这一风险,作者将已审查部分改为使用 可信类型,并启用可信类型强制执行。如果将来存在 其他使用注入接收点的位置,它们将被正确 阻止并报告。
-
某安全团队的任务是确保大量客户端 应用程序代码不包含 XSS 漏洞。由于服务器端 代码是同质的(它主要是 API 后端),并且应用程序 强制执行可信类型,因此审查只关注可信类型 策略及其规则。之后 已审查的策略名称会被 允许出现在 'trusted-types' CSP 指令中,开发者可以安全地 使用。
任何其他代码,包括经常变化的依赖项代码, 都可以从审查中排除,除非它创建可信类型策略。 如果没有策略,该代码就无法导致 DOM XSS。
2. 框架
2.1. 注入接收点
本节为非规范性内容。
注入接收点是一种 强大的 Web API 函数,它只应 使用可信、经过验证或经过适当净化的输入来调用。 使用攻击者控制的(即注入的)输入调用注入接收点 会产生不良后果,并被视为安全漏洞。
注: 本文档涵盖的注入接收点的确切列表 定义于 § 4 集成。
仅通过分析
注入
接收点的调用,很难确定给定应用程序是否包含此类
漏洞(例如它是否易受 DOM XSS 攻击),因为它们的输入(通常是字符串)
不携带其来源信息。例如,虽然
应用程序可能有意使用动态创建的
输入调用 eval()(例如用于代码混淆),但对攻击者
提供的字符串调用 eval() 显然属于安全漏洞——然而
二者并不容易区分。
本文档根据 给定组内接收点所具有的能力将注入接收点划分为多个组。组的强制执行通过 trusted-types-sink-group 值进行控制。
2.1.1. DOM XSS 注入接收点
本节为非规范性内容。
DOM XSS 注入接收点 会以一种可能 在该值不可信时导致 DOM XSS 的方式求值输入字符串值。
示例包括:
-
Element属性的设置器,它们接受要加载的代码 URL, 例如HTMLScriptElement.src, -
Element属性的设置器,它们接受要执行的代码, 例如HTMLScriptElement.text, -
直接执行代码的函数,例如
eval, -
导航到 'javascript:' URL。
由于 HTML 解析器可以创建任意元素(包括脚本)并设置任意属性, DOM XSS 注入接收点还 包括 HTML 解析接收点:
-
解析 HTML 字符串并将其插入文档的函数,例如
Element.innerHTML、ShadowRoot.innerHTML和Element.outerHTML设置器,或 Document.write。 -
使用调用者控制的 标记创建新的同源
Document的函数, 例如parseFromString()。
对 DOM XSS 注入接收点的保护由名为 'script' 的 trusted-types-sink-group 控制。
2.2. 可信类型
为允许作者控制到达注入接收点的值, 我们引入 § 2.2 可信类型。以下 可信类型列表表明 给定值 受到作者信任,可在特定上下文中用于注入接收点。
注: 此上下文中的可信表示 应用程序作者 相信给定值可以安全地用于注入接收点——作者 相信它不会引入漏洞。这并不意味着该 值确实安全。
注: 这允许作者在创建给定 值时指定意图,并允许用户代理根据 该值的类型引入检查,以保留作者的意图。例如,如果 作者打算将某个值用作 HTML 片段,则尝试从 该值加载脚本将会失败。
注: 所有可信类型都包装一个不可变字符串, 该字符串在 创建对象时指定。这些对象在某种意义上不可伪造,因为 JavaScript 没有公开任何方式可以替换给定对象的内部字符串值 ——它存储在没有公开设置器的内部槽中。
注: 所有可信类型的字符串化器都会返回内部 字符串值。 这使得将应用程序代码逐步迁移到使用 可信类型代替 DOM 字符串变得很容易(可以先在应用程序的一部分 开始生成类型,同时仍在代码库的其他部分 使用和接受字符串)。从这个意义上说, 可信类型与常规 DOM API 向后兼容。
2.2.1. TrustedHTML
TrustedHTML 接口表示一个开发者可以
放心插入到注入接收点中的字符串,该接收点会将其渲染为
HTML。
这些对象是围绕字符串的不可变
包装器,通过 TrustedTypePolicy
的
createHTML
方法构造。
[Exposed =(Window ,Worker )]interface TrustedHTML {stringifier ;DOMString toJSON (); };
TrustedHTML 对象具有一个关联的字符串 数据。 该值在对象创建时设置,并且在其生命周期内永远不会改变。
toJSON() 方法步骤以及
TrustedHTML 对象的 字符串化行为步骤是返回关联的数据值。
2.2.2. TrustedScript
TrustedScript 接口表示一个包含未编译
脚本主体的字符串,开发者可以放心地将其传入注入接收点,
后者可能导致执行该脚本。
这些对象是围绕字符串的不可变包装器,
通过 TrustedTypePolicy
的
createScript
方法构造。
[Exposed =(Window ,Worker )]interface TrustedScript {stringifier ;DOMString toJSON (); };
TrustedScript 对象具有一个关联的字符串 数据。 该值在对象创建时设置,并且在其生命周期内永远不会改变。
toJSON() 方法步骤以及
TrustedScript 对象的 字符串化行为步骤是返回关联的数据值。
2.2.3. TrustedScriptURL
TrustedScriptURL 接口表示一个开发者
可以放心传入注入接收点的字符串,后者会将其解析为
外部脚本资源的 URL。
这些对象是围绕
字符串的不可变包装器,通过 TrustedTypePolicy
的
createScriptURL
方法构造。
[Exposed =(Window ,Worker )]interface TrustedScriptURL {stringifier ;USVString toJSON (); };
TrustedScriptURL 对象具有一个关联的字符串 数据。 该值在对象创建时设置,并且在其生命周期内永远不会改变。
toJSON() 方法步骤以及
TrustedScriptURL 对象的 字符串化行为步骤是返回关联的数据值。
2.2.4.
TrustedHTMLParserOptions
TrustedHTMLParserOptions
接口表示开发者
可以放心传入会解析 HTML 的注入接收点的选项。
这些对象是围绕
SetHTMLUnsafeOptions
字典的不可变包装器,通过 TrustedTypePolicy
的
createParserOptions
方法构造。
[Exposed =Window ]interface TrustedHTMLParserOptions { };
TrustedHTMLParserOptions
对象具有一个关联的布尔值 runScripts
以及一个关联的 SanitizerConfig
或 null
净化器配置。
这些值在对象创建时设置,并且在其生命周期内永远不会改变。
2.3. 策略
可信类型只能通过用户定义且 不可变的策略创建,这些策略定义了将字符串转换为 给定可信类型对象的规则。策略允许作者指定 可信类型必须遵循的自定义、 程序化规则。
TrustedHTML
对象随后都可以
安全地用于应用程序中,例如传递给 innerHTML
设置器——即使输入值由攻击者控制,
策略规则也会对其进行中和,使其符合策略特定的
契约。
const sanitizingPolicy= trustedTypes. createPolicy( 'sanitize-html' , { createHTML: ( input) => myTrustedSanitizer( input, { superSafe: 'ok' }), }); myDiv. innerHTML= sanitizingPolicy. createHTML( untrustedValue);
注: 可信类型对象包装由 作者明确信任的值。因此,创建可信类型对象实例实际上会成为一个 注入接收点,因此 创建可信类型 实例的代码对安全至关重要。为严格控制可信类型 对象的创建,我们不直接公开这些对象的构造函数, 而是要求作者通过策略创建它们。
在给定的Realm 中可以创建多个策略,从而允许 应用程序为代码库的不同部分 定义不同规则。
const cdnScriptsPolicy= trustedTypes. createPolicy( 'cdn-scripts' , { createScriptURL( url) { const parsed= new URL( url, document. baseURI); if ( parsed. origin== 'https://mycdn.example' ) { return url; } throw new TypeError ( 'invalid URL' ); }, }); myLibrary. init({ policy: cdnScriptsPolicy});
注: 可信类型对象只能通过
策略创建。如果
启用了强制执行,则只有
策略代码可以触发
注入接收点的操作,因此
策略的 create*
函数的调用点是整个程序中与
注入接收点操作有关的唯一安全敏感代码。
只需对通常占整个代码库很小一部分的这些代码进行
安全审查——无需监控或审查
注入接收点
本身,因为用户代理会强制执行
这些规则,
使这些接收点只接受匹配的可信类型对象,而这些对象反过来
只能通过策略创建。
createPolicy
函数返回一个策略对象,该对象的 create* 函数
会在应用策略
规则后创建可信类型对象。
注: 虽然可以在应用程序的任何位置安全地自由使用
会净化其输入的策略,
但可能需要创建宽松的策略供内部使用,并且仅使用
作者控制的输入调用。例如,客户端 HTML
模板库、HTML 净化器库或 JS 异步
代码插件加载子系统都很可能需要完全控制
HTML 或 URL。API 设计对此提供了支持——每个策略只有在
调用点能够获得该策略的引用(即 createPolicy()
的返回
值)时才能使用。
因此,策略
引用可以被视为
能力,
对其的访问可通过 JavaScript 技术进行控制
(例如通过闭包、内部函数变量或模块)。
( async function renderFootnote() { const unsafePolicy= trustedTypes. createPolicy( 'html' , { createHTML: input=> input, }); const footnoteContent= await fetch( '/footnote.html' ). then( r=> r. text()); footNote. innerHTML= unsafePolicy. createHTML( footnoteContent); })();
2.3.1. 与净化器配合使用
虽然可信类型的构建方式允许使用自定义净化器,
createParserOptions
还允许将它们作为一种
强制使用内置净化器 API 的方式。
( async function renderFootnote() { const footnoteContent= await fetch( '/footnote.html' ). then( r=> r. text()); const policy= trustedTypes. createPolicy( 'html' , { createParserOptions: options=> { const sanitizer= new Sanitizer( options. sanitizer? . get() ?? {}); sanitizer. removeUnsafe(); return { sanitizer, }; } }); footNote. setHTMLUnsafe( footnoteContent, policy. createParserOptions({})); })();
注: 当在解析标记的 HTML 注入
接收点(例如 setHTMLUnsafe()
或 innerHTML)
上强制执行可信类型时,一个 TrustedHTMLParserOptions
对象(从 createParserOptions
获取或由默认策略提供)允许直接解析原始字符串,
而无需 createHTML
或 TrustedHTML
实例。策略作者通常会在 createParserOptions
中配置净化器,以便在解析期间净化不可信标记。对于不支持
解析器选项的纯字符串注入接收点
(例如 srcdoc
或 document.write()),或者对于 XML 文档,原始字符串仍必须通过 createHTML
转换。
2.3.2.
TrustedTypePolicyFactory
TrustedTypePolicyFactory 创建
策略
并验证可信类型对象实例
是否通过其中某个策略创建。
注: 此工厂对象通过全局对象上的
trustedTypes 属性公开给 JavaScript
——参见 § 4.1.1
对 WindowOrWorkerGlobalScope 接口的扩展。
[Exposed =(Window ,Worker )]interface TrustedTypePolicyFactory {TrustedTypePolicy createPolicy (DOMString ,policyName optional TrustedTypePolicyOptions = {});policyOptions boolean isHTML (any );value boolean isScript (any );value boolean isScriptURL (any );value readonly attribute TrustedHTML emptyHTML ;readonly attribute TrustedScript emptyScript ;DOMString ?getAttributeType (DOMString ,tagName DOMString ,attribute optional DOMString ?= "",elementNs optional DOMString ?= "");attrNs DOMString ?getPropertyType (DOMString ,tagName DOMString ,property optional DOMString ?= "");elementNs readonly attribute TrustedTypePolicy ?defaultPolicy ; };
TrustedTypePolicyFactory
对象具有一个关联的 TrustedTypePolicy
默认策略。
其值最初为 null。
TrustedTypePolicyFactory
对象具有一个由字符串组成的关联有序集合 已创建的策略名称。
其值最初为 « »。
createPolicy(policyName, policyOptions)-
创建一个实现 传入
TrustedTypePolicyOptionspolicyOptions 对象中规则的策略对象。 允许的策略名称可能受内容 安全策略限制。 如果策略名称不在 trusted-types CSP 指令定义的允许列表中, 则策略创建会以 TypeError 失败。 此外,如果强制要求策略名称唯一(即未使用'allow-duplicates'), 且使用任意给定policyName多次调用createPolicy, 策略创建会以 TypeError 失败。// HTTP 响应标头:Content-Security-Policy: trusted-types foo trustedTypes. createPolicy( "foo" , {}); // 正常。 trustedTypes. createPolicy( "bar" , {}); // 抛出异常——名称不在允许列表中。 trustedTypes. createPolicy( "foo" , {}); // 抛出异常——名称重复。 返回执行创建可信类型策略算法 的结果,使用以下参数:
const myPolicy= trustedTypes. createPolicy( 'myPolicy' , { // 这段安全关键代码需要进行安全审查; // 此代码中的缺陷可能导致 DOM XSS。 createHTML( input) { return aSanitizer. sanitize( input) }, createScriptURL( input) { const u= new URL( dirty, document. baseURI); if ( APPLICATION_CONFIG. scriptOrigins. includes( u. origin)) { return u. href; } throw new Error ( 'Cannot load scripts from this origin' ); }, }); document. querySelector( "#foo" ). innerHTML= myPolicy. createHTML( aValue); scriptElement. src= myPolicy. createScriptURL( 'https://scripts.myapp.example/script.js' ); isHTML(value)-
如果 value 是
TrustedHTML的实例,并且设置了关联的数据值,则返回 true,否则返回 false。注:
is*函数用于 检查给定对象是否确实是合法的 可信类型对象 (即它是通过配置的某个 策略创建的)。这样可以检测通过 例如 Object.create 或操纵原型链来伪造对象的情况。 isScript(value)-
如果 value 是
TrustedScript的实例,并且设置了关联的数据值,则返回 true,否则返回 false。 isScriptURL(value)-
如果 value 是
TrustedScriptURL的实例,并且设置了关联的数据值,则返回 true,否则返回 false。 getPropertyType(tagName, property, elementNs)-
允许作者检查给定
Element的 属性(IDL 属性)是否需要可信类型。此函数返回以下算法的结果:
-
将 localName 设置为 tagName 的 ASCII 小写形式。
-
如果 elementNs 为 null 或空字符串,则将 elementNs 设置为 HTML 命名空间。
-
令 interface 为 localName 和 elementNs 对应的元素接口。
-
令 expectedType 为 null。
-
在下表中查找一行,其中第一列为 "*" 或 interface 的名称,且 property 位于第二列。 如果找到匹配行,则将 expectedType 设置为 第三列值的接口名称。
元素 属性名称 TrustedType HTMLIFrameElement"srcdoc" TrustedHTMLHTMLScriptElement"innerText" TrustedScriptHTMLScriptElement"src" TrustedScriptURLHTMLScriptElement"text" TrustedScriptHTMLScriptElement"textContent" TrustedScript"*" "innerHTML" TrustedHTML"*" "outerHTML" TrustedHTML -
返回 expectedType。
-
getAttributeType(tagName, attribute, elementNs, attrNs)-
允许作者检查给定
Element的 内容属性是否需要可信类型(如果需要,则是哪一种),从而使之后对Element.setAttribute的调用传递正确的参数类型。此函数返回以下算法的结果:
-
将 localName 设置为 tagName 的 ASCII 小写形式。
-
将 attribute 设置为 attribute 的 ASCII 小写形式。
-
如果 elementNs 为 null 或空字符串,则将 elementNs 设置为 HTML 命名空间。
-
如果 attrNs 是空字符串,则将 attrNs 设置为 null。
-
令 interface 为 localName 和 elementNs 对应的元素接口。
-
令 expectedType 为 null。
-
将 attributeData 设置为执行获取属性的可信类型 数据算法的结果,并使用以下参数:
-
将 interface 作为 element
-
attribute
-
attrNs
-
-
如果 attributeData 不为 null,则将 expectedType 设置为 attributeData 第四个成员的值对应的接口名称。
-
返回 expectedType。
-
emptyHTML,类型为 TrustedHTML, 只读-
是一个
TrustedHTML对象,其数据值设置为空字符串。
emptyScript,类型为 TrustedScript,只读-
是一个
TrustedScript对象,其数据值设置为空字符串。
注: 此对象可用于检测
运行时环境是否支持动态代码编译。
虽然原生可信类型实现可以支持 eval(TrustedScript),但 polyfill
无法
模拟这一行为,因为 eval(TrustedScript) 会返回其输入,而不会解包并求值其中的代码。
// 在原生支持可信类型的情况下,eval(trustedTypes.emptyScript) 会执行并返回假值 undefined。 // 如果不支持,eval(trustedTypes.emptyScript) 会返回真值 Object。 const supportsTS= ! eval( trustedTypes. emptyScript); eval( supportsTS? myTrustedScriptObj: myTrustedScriptObj. toString());
defaultPolicy,类型为 TrustedTypePolicy,只读,可为空-
返回默认策略的值。
2.3.3. TrustedTypePolicy
策略对象实现 TrustedTypePolicy 接口,并定义一
组用于创建可信类型对象的函数。
每个 create* 函数都将字符串值转换为给定的可信类型变体,或者
如果不允许转换给定值,则抛出 TypeError。
[Exposed =(Window ,Worker )]interface TrustedTypePolicy {readonly attribute DOMString ;name TrustedHTML createHTML (DOMString ,input any ...);arguments TrustedScript createScript (DOMString ,input any ...);arguments TrustedScriptURL createScriptURL (DOMString ,input any ...); [arguments Exposed =Window ]TrustedHTMLParserOptions createParserOptions (optional SetHTMLUnsafeOptions = {},options any ...); };arguments
每个策略都有一个名称。
每个 TrustedTypePolicy 对象都有一个关联的 TrustedTypePolicyOptions
选项对象,用于描述策略的实际行为。
createHTML(input, ...arguments)-
返回 使用以下参数执行创建可信类型算法的 结果:
- policy
- this 值
- trustedTypeName
"TrustedHTML"- value
- input
- arguments
- arguments
createScript(input, ...arguments)-
返回 使用以下参数执行创建可信类型算法的 结果:
- policy
- this 值
- trustedTypeName
"TrustedScript"- value
- input
- arguments
- arguments
createScriptURL(input, ...arguments)-
返回 使用以下参数执行创建可信类型算法的 结果:
- policy
- this 值
- trustedTypeName
"TrustedScriptURL"- value
- input
- arguments
- arguments
createParserOptions(options, ...arguments)-
返回 使用以下参数执行创建可信类型算法的 结果:
- policy
- this 值
- trustedTypeName
"TrustedHTMLParserOptions"- value
- options
- arguments
- arguments
2.3.4.
TrustedTypePolicyOptions
此字典保存作者定义的、用于将字符串
值转换为可信值的函数。这些函数不会直接创建可信类型
对象实例——此行为由
TrustedTypePolicy
提供。
dictionary TrustedTypePolicyOptions {CreateHTMLCallback ;createHTML CreateScriptCallback ;createScript CreateScriptURLCallback ;createScriptURL CreateParserOptionsCallback ; };createParserOptions callback =CreateHTMLCallback DOMString ? (DOMString ,input any ...);arguments callback =CreateScriptCallback DOMString ? (DOMString ,input any ...);arguments callback =CreateScriptURLCallback USVString ? (DOMString ,input any ...);arguments callback =CreateParserOptionsCallback SetHTMLUnsafeOptions ? (SetHTMLUnsafeOptions ,options any ...);arguments
2.3.5. 默认策略
本节为非规范性内容。
其中一个策略,即名称为
"default" 的策略,是特殊的;
当一个注入接收点收到
一个字符串(而不是
可信类型对象)时,用户代理会隐式调用此策略,
并分别传入不可信的字符串值、该接收点的可信类型和
接收点类型。
这允许应用程序定义一种后备行为,用来替代 产生违规。其目的是让应用程序能够从 意外的数据流中恢复,并在 “最后手段”的情况下净化可能由攻击者控制的字符串,或者在 无法创建安全值时拒绝该值。从策略内部抛出的错误会 传播到应用程序。
如果默认策略不存在,或其相应的 create* 函数
返回 null 或 undefined,则会导致 CSP 违规。在
强制模式下会抛出错误,而在仅报告模式下,会使用
传递给默认策略的原始值。
注: 此可选行为允许向 仍在使用使用注入接收点的旧代码的应用程序引入可信类型强制执行。 不言而喻,此策略 必须使用非常严格的规则定义,以免绕过应用程序未知部分中的 安全限制。在极端 情况下,一个宽松、无操作的默认策略会破坏使用可信类型 来保护对注入 接收点访问的全部收益。如果可能, 作者应只在过渡期使用默认策略, 使用它来检测并重写不安全使用注入 接收点的依赖项,并最终完全淘汰默认策略的使用。
注: 有关 默认策略如何应用的详细信息,请参见 § 3.5 获取符合可信类型要求的字符串。
// Content-Security-Policy: trusted-types default; require-trusted-types-for 'script' trustedTypes. createPolicy( 'default' , { createScriptURL: ( value, type, sink) => { console. log( "Please refactor." ); return value+ '?default-policy-used&type=' + encodeURIComponent( type) + '&sink=' + encodeURIComponent( sink); } }); aScriptElement. src= "https://cdn.example/script.js" ; // 请重构。 console. log( aScriptElement. src); // https://cdn.example/script.js?default-policy-used&type=TrustedScriptURL&sink=HTMLScriptElement%20src
2.4. 强制执行
注: 强制执行是在值 到达注入接收点之前检查其是否具有适当类型的过程。
允许作者创建策略及其可信类型对象的 JavaScript API 始终
可用(通过 trustedTypes)。
由于注入接收点
会将其安全敏感
参数字符串化,而可信类型
对象会字符串化为其内部字符串值,因此作者
可以使用可信类型来代替字符串。
为了保护对注入接收点的访问,除了使用可信 类型的 JavaScript 代码之外, 用户代理还需要强制执行它们,即断言给定组中的注入接收点 绝不 使用字符串值调用,而改用可信类型值。本节说明作者 如何控制这种强制执行行为。
作者还可以通过指定有关策略创建的规则来 控制其策略。
2.4.1. 内容安全策略
应用程序可以通过配置内容安全策略来控制可信类型强制执行。本文档 定义了与可信类型规则对应的新指令。 require-trusted-types-for 指令指定 应要求类型的注入接收点组。trusted-types 指令 控制如何创建策略。
注: 使用 CSP 机制允许作者通过使用 Content-Security-Policy-Report-Only HTTP 响应标头,为应用程序准备启用可信类型强制执行。
注: 大多数强制执行规则被定义为对 其他规范中算法的 修改,参见 § 4 集成。
2.4.2.
使用 createParserOptions
强制执行净化
createHTML
依赖使用 JS 净化器在字符串注入解析器之前对其进行净化,
而 createParserOptions
则允许页面的默认策略强制执行 HTML 净化。
默认策略中的 createParserOptions
回调会在
HTML 片段接收点使用未经审查的解析器选项(或默认选项)调用时运行,从而允许策略
审查调用者提供的选项,
并且即使输入标记已经是 TrustedHTML
的实例,也能强制执行净化。
Content-Security-Policy: require-trusted-types-for 'script'
使用 HTML 注入接收点时注入净化器。
( async function renderFootnote() { trustedTypes. createPolicy( 'default' , { createParserOptions: options=> { const sanitizer= new Sanitizer( options. sanitizer? . get() ?? {}); sanitizer. removeUnsafe(); return { ... options, sanitizer}; } }); const trustedOptions= trustedTypes. createPolicy( 'trusted' , { createParserOptions: options=> options}). createParserOptions({}); const untrustedFootnoteContent= await fetch( '/footnote.html' ). then( r=> r. text()); // 此 HTML 将使用“安全”的 HTML 净化器进行净化,因为默认策略注入了 // 一个移除了不安全标记的净化器。 footNote. innerHTML= untrustedFootnoteContent; // 或: footNote. setHTMLUnsafe( untrustedFootnoteContent, {}); const trustedMainContent= await fetch( "main.html" ). then( r=> r. text()); main. setHTMLUnsafe( trustedMainContent, trustedOptions); })();
除净化外,默认策略还可以通过覆盖调用者的 runScripts
设置来控制 HTML 注入是否执行脚本。
使用 runScripts
设置为 false 插入的 HTML 仍可以向文档插入 script 元素,
但这些脚本不会自动执行。
( async function renderFootnote() { trustedTypes. createPolicy( 'default' , { createHTML: string=> string, createParserOptions: options=> { return { ... options, runScripts: false }; } }); // 默认策略会将 runScripts 值覆盖为 false。 main. setHTMLUnsafe( someHTMLWithScripts, { runScripts: true }); // 这同样适用于 Range.prototype.createContextualFragment() const fragment= new Range(). createContextualFragment( "<script>alert(1)</" + "script>" ); const div= document. createElement( 'div' ); // 片段中的脚本不会执行,因为默认策略会覆盖 runScripts。 div. appendChild( fragment); })();
2.4.3. 输入强制执行摘要
本节为非规范性内容。
下表总结了在强制执行 内容安全策略的情况下,获取符合可信类型 要求的输入针对各种参数组合和默认策略回调的行为:
| documentType | options | input | 默认策略状态 / 回调 | 结果 | 有效 sanitizer
| 理由 |
|---|---|---|---|---|---|---|
"html"
| TrustedHTMLParserOptions
| 字符串或 TrustedHTML
| (忽略) | 返回 (stringified |input|, |options|)。
| options 的净化器配置 | 调用者提供的 TrustedHTMLParserOptions
明确授权解析操作,而脚本执行和净化由
创建它的策略决定。
|
"html"
| 字典(调用者提供 sanitizer)
| TrustedHTML
| createParserOptions
返回配置策略净化器的字典
| 返回 (stringified |input|, |compliantOptions|)。
| 由 createParserOptions
配置
| 策略审查或替换 TrustedHTML 上调用者的净化器: 尽管
input 是经过确认的 TrustedHTML
实例,createParserOptions
仍会运行,并在 argument["sanitizer"] 中接收调用者的净化器。策略可以
检查、强制执行或替换净化器配置(以及控制脚本执行),
从而确保未经审查的调用者提供选项无法绕过策略审查。
|
字典(调用者提供 sanitizer)
| createParserOptions
返回 {}(省略 sanitizer)
| 返回 (stringified |input|, |compliantOptions|)。
| null
| 策略移除调用者的净化器: 默认策略决定最终 解析器选项。如果策略没有返回净化器,则解析期间不会进行净化, 从而覆盖调用者的请求。 | ||
| 不是由作者提供或不需要 审查的字典 | 没有 createParserOptions
(或没有默认策略)
| 返回 (stringified |input|, |options|)。
| null
| 没有解析器策略的 TrustedHTML: 当没有策略定义 createParserOptions
时,现有的 TrustedHTML
实例会直接满足可信类型要求(绕过 createHTML),
前提是作者提供的选项不需要审查。
| ||
| 作者提供且需要审查的字典 | 抛出 TypeError。
| 不适用 | 拒绝未经审查的选项: TrustedHTML
在使用未经审查的净化器或启用脚本执行时可能变得不安全,因此这些选项需要 TrustedHTMLParserOptions
或默认策略的 createParserOptions。
| |||
"html"
| 字典 | 字符串 | createParserOptions
返回一个字典
| 返回 (stringified |input|, |compliantOptions|)。
| 由 createParserOptions
配置(或为 null)
| 解析器策略授权解析原始字符串: 默认策略返回
符合要求的解析器选项,从而授权原始字符串解析,并配置净化和脚本
执行,而不要求 createHTML。
|
| 字典 | 字符串或 TrustedHTML
| createParserOptions
抛出异常
| 重新抛出该异常。 | 不适用 | 策略回调中的异常会立即传播给调用者,无论
input 是字符串还是 TrustedHTML。
| |
createParserOptions
返回 null 或 undefined
| 抛出 TypeError。
| 不适用 | 策略回调返回 null 或 undefined 会拒绝该值,从而触发 CSP 违规
错误,无论 input 是字符串还是 TrustedHTML。
| |||
| 作者提供且需要审查的字典 | 字符串 | 没有 createParserOptions
(或没有默认策略)
| 抛出 TypeError。
| 不适用 | 拒绝未经审查的选项: 不会调用 createHTML,
因为其结果将使用未经审查的选项进行解析。
| |
| 不是由作者提供或不需要 审查的字典 | 字符串 | 没有 createParserOptions;
createHTML
返回 TrustedHTML
| 返回 (stringified |convertedInput|, |options|)。
| null
| 提供向后兼容性:当没有策略管理解析器选项时,接收点会回退到
通过 createHTML
审查或净化标记字符串。
| |
没有 createParserOptions;
createHTML
抛出异常
| 重新抛出该异常。 | 不适用 | 策略回调中的异常会立即传播给调用者。 | |||
没有 createParserOptions;
createHTML
返回 null 或 undefined
| 抛出 TypeError。
| 不适用 | 被 createHTML
拒绝会触发 CSP 违规错误。
| |||
| 没有默认策略(或两个回调均未定义) | 抛出 TypeError。
| 不适用 | 在强制执行 CSP 的情况下,如果没有策略授权 解析器选项或标记字符串,就无法解析原始字符串。 | |||
"xml"
| 任意 | TrustedHTML
| (任意) | 返回 (stringified |input|, |options|)。
| 无(忽略) | XML 接收点需要可信标记;TrustedHTML
实例直接满足这一要求。XML 片段解析不支持净化,
并且永远不会执行脚本。
|
"xml"
| 任意 | 字符串 | createHTML
返回 TrustedHTML
| 返回 (stringified |convertedInput|, |options|)。
| 无(忽略) | XML 片段接收点不支持解析器选项绕过或净化;标记字符串必须
始终通过 createHTML
转换。
XML 片段解析不支持净化,并且永远不会执行脚本。
|
createHTML
抛出异常
| 重新抛出该异常。 | 不适用 | 策略回调中的异常会立即传播给调用者。 | |||
没有 createHTML
或没有默认策略(或返回 null/undefined)
| 抛出 TypeError。
| 不适用 | 如果没有 createHTML,
则无论解析器选项如何,都不能将不可信字符串注入 XML 接收点。
|
TrustedHTML、runScripts 和净化: 强制执行可信类型的接收点按以下方式处理选项和 脚本:
- 当 input 是
TrustedHTML实例时,默认策略的createParserOptions仍会审查调用者提供的任何选项字典,使策略能够检查、配置或 覆盖净化器配置(以及控制脚本执行),即使输入已经 是TrustedHTML。 如果createParserOptions抛出异常或返回null或undefined,则操作会被拒绝。当createParserOptions不存在时,作者提供且需要审查的选项字典会被 拒绝,无论 input 是TrustedHTML实例,还是通过createHTML转换的字符串。 接收点自行构造的选项,例如createContextualFragment()的runScripts设置为 true,不会被拒绝。 - 当 options 是
TrustedHTMLParserOptions时, 脚本执行和净化由创建选项对象的策略控制。当 选项作为字典传递时,默认策略的createParserOptions决定最终的脚本执行行为,并覆盖调用者请求的runScripts设置。 - XML 片段解析不支持净化;对于 XML 接收点,任何净化器配置都会被忽略。
- 对于流式 HTML 片段解析,会直接调用获取符合可信类型要求的解析器选项,
并将 throwIfMissing 设置为 true。在这种情况下,如果
createParserOptions缺失、抛出异常或返回null或undefined,则会立即抛出(或重新抛出)TypeError。
3. 算法
3.1. 创建可信类型策略
要创建
可信类型策略,给定一个 TrustedTypePolicyFactory
(factory)、
一个字符串(policyName)、一个 TrustedTypePolicyOptions
字典(options),以及一个
全局对象(global),运行以下步骤:
-
令 allowedByCSP 为执行可信类型 策略创建是否应被内容安全策略阻止?算法的结果,并传入 global、 policyName 以及 factory 的已创建策略名称值。
-
如果 allowedByCSP 为
"Blocked",则抛出 TypeError 并中止后续步骤。 -
如果 policyName 为
default,且 factory 的默认策略 值不为 null,则抛出 TypeError 并中止后续步骤。 -
令 policy 为一个新的
TrustedTypePolicy对象。 -
将 policy 的
name属性值设置为 policyName。 -
将 policy 的选项值设置为 «[ "createHTML" -> options["
createHTML"], "createScript" -> options["createScript"], "createScriptURL" -> options["createScriptURL"], "createParserOptions" -> options["createParserOptions"] ]»。 -
如果 policyName 为
default,则将 factory 的默认策略值设置为 policy。 -
返回 policy。
3.2. 创建可信类型
要创建可信
类型,给定一个 TrustedTypePolicy
policy、类型名称 trustedTypeName、
字符串或字典 value 以及列表 arguments,执行以下步骤:
-
令 policyValue 为使用与本算法相同的参数执行获取可信 类型策略值的结果,并另外将 true 作为 throwIfMissing。
-
如果该算法抛出错误,则重新抛出该错误并中止后续步骤。
-
如果 trustedTypeName 为
"TrustedHTMLParserOptions":-
如果 policyValue 为 null,则抛出
TypeError。注: 从 命名策略的
createParserOptions回调返回null会在此处抛出TypeError, 而从createHTML、createScript或createScriptURL返回null或undefined则会得到空字符串。 -
令 sanitizerConfig 为 从 policy 的相关 Realm和 policyValue 获取净化器 配置的结果。
-
令 runScripts 为 policyValue["runScripts"],默认值为 false。
-
在 policy 的相关 Realm中返回一个新的
TrustedHTMLParserOptions实例,其 净化器 配置设置为 sanitizerConfig,并将其 runScripts 设置为 runScripts。
-
-
令 dataString 为将 policyValue 字符串化的结果。
-
如果 policyValue 为 null 或 undefined,则将 dataString 设置为空字符串。
-
返回类型 名称为 trustedTypeName 的接口的新实例,并将其关联的数据值设置为 dataString。
3.3. 获取可信类型策略值
要获取可信
类型策略值,给定一个 TrustedTypePolicy
policy、类型名称 trustedTypeName、
字符串或字典 value、列表 arguments 以及布尔值
throwIfMissing,执行以下步骤:
-
令 functionName 为给定 trustedTypeName 对应的函数名称, 根据下表确定:
函数名称 可信类型名称 "createHTML" "TrustedHTML" "createScript" "TrustedScript" "createScriptURL" "TrustedScriptURL" "createParserOptions" "TrustedHTMLParserOptions" -
令 function 为 policy 的选项[functionName]。
-
如果 function 为
null,则:-
如果 throwIfMissing 为 true,则抛出 TypeError。
-
否则返回
null。
-
-
如果 trustedTypeName 为
"TrustedHTMLParserOptions":-
将 value 设置为给定 policy 的相关 Realm和 value 创建解析器选项 回调参数的结果。
-
-
令 args 为 « value »。
-
将 arguments 中的每一项追加到 args。
-
令 policyValue 为使用 args 和
"rethrow"调用 function 的结果。 -
返回 policyValue。
3.4. 获取符合可信类型要求的输入
注: 有关此 算法针对各种参数组合和默认策略回调的行为摘要,请参见 § 2.4.3 输入强制执行摘要。
要获取符合可信
类型要求的输入,给定一个全局对象 global、一个字符串或 TrustedHTML
input、
一个 TrustedHTMLParserOptions、
ParseHTMLUnsafeOptions
或 SetHTMLUnsafeOptions
options、字符串 sink、可选的 "html" 或 "xml"
documentType(默认为 "html"),以及可选的布尔值 optionsFromAuthor
(默认为 true):
-
令 compliantOptions 为 options。
-
如果 documentType 为
"html":-
将 compliantOptions 设置为调用获取符合可信类型要求的 解析器选项的结果,并传入 global、options、false、 sink 和 optionsFromAuthor。
注: 自行构造 options 而不是从作者处获取它们的接收点,会为 optionsFromAuthor 传入 false。 例如,
createContextualFragment()会将runScripts设置为 true。 -
如果 compliantOptions 是
TrustedHTMLParserOptions的实例,则返回(字符串化后的 input,compliantOptions)。
-
-
令 compliantHTML 为调用获取 符合可信类型要求的字符串的结果,并传入
TrustedHTML、 global、input、sink 和"script"。 -
如果该算法抛出错误,则重新抛出该错误。
-
返回(compliantHTML,compliantOptions)。
3.5. 获取符合可信类型要求的字符串
此算法将返回一个可用于 注入接收点的字符串,并可选择 从匹配的可信类型中将其解包。 它将确保可信类型强制执行规则得到遵守。
要获取
符合可信类型要求的字符串,给定一个 TrustedType
类型(expectedType)、一个全局对象(global)、
TrustedType
或字符串(input)、字符串(sink)和字符串(sinkGroup),运行以下
步骤:
-
如果 input 是 expectedType 的实例,则返回字符串化后的 input 并中止这些步骤。
-
令 requireTrustedTypes 为执行接收点类型是否需要可信类型? 算法的结果, 并传入 global、sinkGroup 和 true。
-
如果 requireTrustedTypes 为
false,则返回字符串化后的 input 并 中止这些步骤。 -
令 convertedInput 为使用 与本算法相同的参数执行使用默认策略处理值的结果。
-
如果该算法抛出错误,则重新抛出该错误并中止后续步骤。
-
如果 convertedInput 为
null或undefined,则执行以下 步骤:-
令 disposition 为执行接收点 类型不匹配违规是否应被内容安全策略阻止?算法的结果, 并传入 global、sink、sinkGroup,以及字符串化后的 input 作为 source。
-
如果 disposition 为
“Allowed”,则返回字符串化后的 input 并 中止后续步骤。注: 此步骤确保默认 策略的拒绝会被报告,但在仅报告模式下会被忽略。
-
抛出 TypeError 并中止后续步骤。
-
-
断言:convertedInput 是 expectedType 的实例。
-
返回字符串化后的 convertedInput。
3.6. 获取符合可信类型要求的解析器选项
注: 从
获取符合可信类型要求的输入调用时,throwIfMissing 为
false。即使如此,
作者提供且需要审查的选项也需要一个带有 createParserOptions
的默认策略。
对于同步 HTML 片段注入接收点,结果选项中的 TrustedHTMLParserOptions
可以满足可信类型强制执行,而无需对输入字符串调用 createHTML。
在流式传输或无法预先验证 HTML 字符串的上下文中,调用者为
throwIfMissing 传入 true,以确保必须存在带有 createParserOptions
的默认策略。
对于 XML 文档,解析器选项无法满足可信类型强制执行;XML 片段接收点始终
要求通过获取符合可信类型要求的字符串获得符合要求的字符串输入。
要获取符合可信类型要求的解析器选项,给定一个
全局对象 global、
input,其为 TrustedHTMLParserOptions、
SetHTMLUnsafeOptions
或 ParseHTMLUnsafeOptions,
一个布尔值 throwIfMissing、一个字符串 sink 和一个可选的布尔值
optionsFromAuthor(默认为 true):
-
如果 input 是
TrustedHTMLParserOptions的实例,则返回 input。 -
令 requireTrustedTypes 为执行接收点类型是否需要可信类型? 算法的结果, 并传入 global、
"script"和 true。 -
如果 requireTrustedTypes 为
false,则返回 input。 -
令 requirePolicy 为 throwIfMissing。
-
如果 optionsFromAuthor 为 true 且 input 需要审查, 则将 requirePolicy 设置为 true。
注: 已作为
TrustedHTML审查过的标记,在使用未经审查的净化器(例如使用replaceWithChildrenElements的净化器)解析或启用脚本执行时,可能变得不安全。 此类选项需要来自TrustedHTMLParserOptions或默认策略的createParserOptions。 -
如果 defaultPolicy 为 null:
-
如果 requirePolicy 为 true:
-
令 disposition 为执行接收点 类型不匹配违规是否应被内容安全策略阻止? 算法的结果, 并传入 global、sink、
"script",以及空 字符串作为 source。 -
如果 disposition 为
“Allowed”,则返回 input。 -
抛出
TypeError。
-
-
返回 input。
-
-
令 function 为 defaultPolicy 的选项["createParserOptions"]。
-
如果 function 为 null:
-
如果 requirePolicy 为 true:
-
令 disposition 为执行接收点 类型不匹配违规是否应被内容安全策略阻止? 算法的结果, 并传入 global、sink、
"script",以及空 字符串作为 source。 -
如果 disposition 为
“Allowed”,则返回 input。 -
抛出
TypeError。
-
-
返回 input。
-
-
令 argument 为给定 global 的相关 Realm和 input 创建解析器选项回调 参数的结果。
-
令 policyValue 为使用 « argument, "TrustedHTMLParserOptions", sink » 和
"rethrow"调用 function 的结果。 -
如果该算法抛出错误,则重新抛出该错误并中止后续步骤。
-
如果 policyValue 为
null或undefined:-
令 disposition 为执行接收点 类型不匹配违规是否应被内容安全策略阻止?算法的结果, 并传入 global、sink、
"script",以及空字符串作为 source。 -
如果 disposition 为
“Allowed”,则返回 input。注: 此步骤确保默认 策略的拒绝会被报告,但在仅报告模式下会被忽略。
-
抛出
TypeError。
-
-
令 runScripts 为 policyValue["runScripts"],默认值为 false。
注: 作为默认策略调用时,
createParserOptions回调决定最终的脚本执行行为,并覆盖调用者请求的runScripts选项。 -
在 global 的相关 Realm中返回一个新的
TrustedHTMLParserOptions, 其净化器配置 设置为 从 global 的相关 Realm和 policyValue 获取净化器配置的结果, 并将其runScripts 设置为 runScripts。
如果一个 SetHTMLUnsafeOptions
或 ParseHTMLUnsafeOptions
options 满足以下条件,则需要审查:
options["runScripts"] 存在且为 true,或者 options["sanitizer"] 存在且不是空的
SanitizerConfig。
注: 空的 SanitizerConfig
不会更改解析后的标记。
要创建解析器选项回调参数,给定一个 Realm realm 和一个字典 dictionary:
-
令 runScriptsInput 为 dictionary["runScripts"],默认值为 false。
-
令 argument 为有序映射 «[ "runScripts" → runScriptsInput ]»。
-
令 sanitizerInput 为从 realm 和 dictionary 获取 净化器的结果。
-
如果 sanitizerInput 不为 null,则将 argument["sanitizer"] 设置为 sanitizerInput。
-
返回 argument。
要从 字典获取净化器,给定一个Realm realm 和一个字典 dictionary:
-
令 sanitizerInput 为 dictionary["sanitizer"],默认为 null。
-
如果 sanitizerInput 为 null,则返回 null。
-
令 configuration 为 null。
-
如果 sanitizerInput 是
SanitizerPresets: -
否则,如果 sanitizerInput 是
Sanitizer:-
将 configuration 设置为 sanitizerInput 的配置。
-
-
否则,如果 sanitizerInput 是
SanitizerConfig:-
将 configuration 设置为 sanitizerInput。
-
-
断言: configuration 不为 null。
-
令 sanitizer 为 realm 中的一个新
Sanitizer实例。 -
给定 configuration 和 true,配置 sanitizer。
-
返回 sanitizer。
要从字典获取净化器配置副本,给定 一个Realm realm 和一个字典 dictionary:
3.7. 使用默认策略处理值
此算法通过默认策略(如果存在)路由要分配给注入接收点的值。
要使用默认策略处理值,给定一个 TrustedType
类型(expectedType)、一个全局对象(global)、
TrustedType
或字符串(input),以及字符串(sink),运行以下步骤:
-
令 policyValue 为执行获取可信 类型策略值的结果,并使用以下参数:
-
将 defaultPolicy 作为 policy
-
将字符串化后的 input 作为 value
-
将 expectedType 的类型名称作为 trustedTypeName
-
将 « trustedTypeName, sink » 作为 arguments
-
将 false 作为 throwIfMissing
-
-
如果该算法抛出错误,则重新抛出该错误并中止后续步骤。
-
如果 policyValue 为 null 或 undefined,则返回 policyValue。
-
令 dataString 为将 policyValue 字符串化的结果。
-
返回类型 名称为 trustedTypeName 的接口的新实例,并将其关联的数据值设置为 dataString。
3.8. 准备脚本文本
要准备脚本
文本,给定一个 HTMLScriptElement
或 SVGScriptElement
(script),执行以下步骤:
-
如果 script 是
HTMLScriptElement,则令 sink 为 "HTMLScriptElement text"; 否则为 "SVGScriptElement text"。 -
如果 script 的脚本文本值不等于其子文本内容, 则将 script 的脚本文本设置为执行获取符合可信类型要求的字符串的结果,并使用 以下参数:
-
将
TrustedScriptURL作为 expectedType, -
将 script 的子文本内容属性值作为 input,
-
sink,
-
将
'script'作为 sinkGroup。
如果该算法抛出错误,则重新抛出该错误。
-
3.9. 获取符合可信类型要求的属性值
要获取符合可信类型要求的属性值,给定
字符串 attributeName、字符串 attributeNs、Element
element 以及 TrustedType
或字符串 newValue,执行以下步骤:
-
如果 attributeNs 是空字符串,则将 attributeNs 设置为 null。
-
将 attributeData 设置为执行获取属性的可信类型数据 算法的结果,并使用以下参数:
-
element
-
attributeName
-
attributeNs
-
-
如果 attributeData 为 null,则:
-
如果 newValue 是字符串,则返回 newValue。
-
断言:newValue 是
TrustedHTML或TrustedScript或TrustedScriptURL。 -
返回 value 的关联数据。
-
-
令 expectedType 为 attributeData 第四个成员的值。
-
令 sink 为 attributeData 第五个成员的值。
-
返回使用以下参数执行获取符合可信类型要求的字符串的 结果:
如果该算法抛出错误,则重新抛出该错误。
3.10. 获取属性的可信类型数据
要获取 属性的可信类型数据,给定 element、attribute、 attributeNs,执行以下步骤:
下文使用的事件处理器内容属性概念 存在歧义。本规范需要一种更好的机制来识别事件处理器属性。参见 https://github.com/w3c/trusted-types/issues/520。
-
令 data 为 null。
-
如果 attributeNs 为 null,且 « HTML 命名空间、SVG 命名空间、MathML 命名空间 » 包含 element 的命名空间,且 attribute 是一个 事件处理器内容属性的名称:
-
返回(
Element、 null、attribute、TrustedScript、 "Element " + attribute)。
-
-
在下表中查找一行,其中 element 位于第一列, attributeNs 位于第二列, attribute 位于第三列。 如果找到匹配的行,则将 data 设置为该行。
元素 属性命名空间 属性局部名称 TrustedType 接收点 HTMLIFrameElementnull "srcdoc" TrustedHTML"HTMLIFrameElement srcdoc" HTMLScriptElementnull "src" TrustedScriptURL"HTMLScriptElement src" SVGScriptElementnull "href" TrustedScriptURL"SVGScriptElement href" SVGScriptElementXLink 命名空间 "href" TrustedScriptURL"SVGScriptElement href" -
返回 data。
4. 集成
typedef (TrustedHTML or TrustedScript or TrustedScriptURL );TrustedType
4.1. 与 HTML 集成
Window
和 Worker
对象具有一个可信类型策略工厂,
它是一个 TrustedTypePolicyFactory
对象。
4.1.1. 对 WindowOrWorkerGlobalScope 接口的扩展
本文档扩展了由 HTML 定义的 WindowOrWorkerGlobalScope
接口:
partial interface mixin WindowOrWorkerGlobalScope {readonly attribute TrustedTypePolicyFactory ; };trustedTypes
trustedTypes
getter 步骤是返回 this
的相关全局对象的可信
类型策略工厂。
4.1.2. 脚本强制执行
本文档修改了如何设置 HTMLScriptElement
的子文本内容,以允许应用程序
控制动态创建的脚本。为此,它
直接在 HTMLScriptElement
上添加 innerText
和 textContent
属性。
这些属性的行为与
原始对应属性保持相同,只是增加了调用获取符合可信
类型要求的字符串的行为。
注: 使用这些 IDL 属性是 动态设置脚本 URL 或文本的推荐方式。直接操作属性节点或文本节点 会在准备脚本时针对最终值调用默认策略。
partial interface HTMLScriptElement { [CEReactions ]attribute (TrustedScript or [LegacyNullToEmptyString ]DOMString ); [innerText CEReactions ]attribute (TrustedScript or DOMString )?; [textContent CEReactions ]attribute (TrustedScriptURL or USVString ); [src CEReactions ]attribute (TrustedScript or DOMString ); };text
4.1.2.1. 具有可信值的槽
一个 HTMLScriptElement
和 SVGScriptElement
具有:
- 一个关联的字符串 脚本文本。
-
一个字符串,包含通过 符合要求的接收点设置的待执行脚本主体。等同于脚本的 子文本内容。最初为空字符串。
4.1.2.2.
innerText
IDL 属性
innerText
setter 步骤如下:
-
令 value 为使用
TrustedScript、 this 的相关全局对象、给定值、HTMLScriptElement innerText和script调用获取 符合可信类型要求的字符串的结果。
innerText
getter 步骤如下:
4.1.2.3.
textContent
IDL 属性
textContent
setter 步骤是:如果给定值为 null,则改为将其视为
空字符串,然后按以下说明执行:
-
令 value 为使用
TrustedScript、 this 的 相关全局对象、给定值、HTMLScriptElement textContent和script调用获取 符合可信类型要求的字符串的结果。
textContent
getter 步骤如下:
注: 目前我们没有为 SVGScriptElement
添加等效项。
参见 https://github.com/w3c/trusted-types/issues/512。
4.1.2.4.
text
IDL 属性
按如下方式更新 text
setter 步骤算法。
-
令 value 为使用
TrustedScript、 this 的 相关全局对象、给定值、HTMLScriptElement text和script调用获取 符合可信类型要求的字符串的结果。 - 将 this 的脚本文本值设置为给定值。
4.1.2.5.
src
IDL 属性
src
getter 步骤如下:
- 令 element 为运行 this 的获取 元素所得的结果。
- 令 contentAttributeValue 为运行 this 的获取内容 属性所得的结果。
- 如果 contentAttributeValue 为 null,则返回空字符串。
- 令 urlString 为给定 contentAttributeValue,相对于 element 的节点文档,对 URL 进行编码、解析并序列化的结果。
- 如果 urlString 不是失败,则返回 urlString。
- 返回转换为标量值字符串的 contentAttributeValue。
src
setter 步骤如下:
-
令 value 为使用
TrustedScriptURL、 this 的 相关全局对象、给定值、HTMLScriptElement src和script调用获取 符合可信类型要求的字符串的结果。 - 将 this 的 src 内容属性设置为 value。
4.1.2.6. 从解析器设置槽值
本文档修改 HTML 解析器,使其在创建脚本时设置脚本文本值。
按如下方式修改文本插入模式算法:
- 标签名为 "script" 的结束标签
-
...
如果活动的推测性 HTML 解析器为 null,则准备脚本 元素 script。这可能会导致某些脚本执行,从而可能导致 新字符被插入分词器,并且 可能导致分词器输出更多 token,从而造成解析器的可重入 调用。
...
上述算法 没有考虑在解析过程中脚本元素内容发生变化的情况。实现者必须 确保防范这种情况。参见 https://github.com/w3c/trusted-types/issues/507。
对 SVG 脚本元素的处理
尚无适当的定义。不过,实现必须对 SVGScriptElement
的处理应用类似的更改。
4.1.2.7. 槽值验证
准备脚本元素算法的前几个步骤修改 如下:
-
如果 el 的 已启动为 true,则返回。
-
令 parser document 为 el 的解析器文档。
-
将 el 的解析器文档设置为 null。
这样做是为了让解析器插入的
script元素如果在解析器尝试运行它们时运行失败, 例如因为它们为空或指定了不支持的 脚本语言,则另一个脚本之后仍可以改变它们并使其再次运行。 -
如果 parser document 非 null 且 el 没有
async属性,则将 el 的强制异步设置为 true。这样做是为了让解析器插入的
script元素如果在 解析器尝试运行它时运行失败,但后来在脚本动态 更新它之后执行,那么即使async属性未设置,它也会以异步方式执行。 -
在 el 上执行准备脚本文本算法。 如果该算法抛出错误,则返回。
- ...
对 SVG 脚本元素的处理
尚无适当的定义。不过,实现必须对 SVGScriptElement
的处理应用类似的更改。
4.2. 与内容安全策略集成
4.2.1. require-trusted-types-for 指令
本文档定义 require-trusted-types-for——一种新的内容安全策略 指令。
require-trusted-types-for 指令为当前 Realm 中特定组的所有注入接收点配置可信 类型框架。 具体而言,它定义了将字符串值传递给给定组的注入接收点 时应采取的行为(即是否应为此类接收点启用基于类型的强制执行)。
注: 目前,仅规定了对 § 2.1.1 DOM XSS 注入接收点的强制执行。
directive-name = "require-trusted-types-for" directive-value = trusted-types-sink-group-keyword *( required-ascii-whitespace trusted-types-sink-group-keyword) trusted-types-sink-group-keyword = "'" trusted-types-sink-group "'" trusted-types-sink-group = "script"
4.2.1.1. require-trusted-types-for
导航前检查
给定一个请求(request)、字符串 navigation type 和一个
策略(policy),如果导航违反
require-trusted-types-for 指令的约束,此算法返回
"Blocked",
否则返回 "Allowed"。这构成 require-trusted-types-for 指令的导航前检查:
注: 此算法确保通过导航到
javascript: URL 而执行的代码除了受到其他
CSP 指令施加的所有其他限制之外,还必须经过默认
策略的 createScript 函数。
-
令 encodedScriptSource 为从 urlString 中移除开头的
"javascript:"所得的结果。 -
令 convertedScriptSource 为执行使用默认策略处理值 算法的结果,并使用以下参数:
-
将
TrustedScript作为 expectedType -
将 encodedScriptSource 作为 input
-
将
"Location href"作为 sink
如果该算法抛出错误,或 convertedScriptSource 不是
TrustedScript对象,则返回 "Blocked" 并中止后续步骤。 -
-
将 urlString 设置为在字符串化后的 convertedScriptSource 前添加
"javascript:"所得的结果。 -
令 newURL 为在 urlString 上运行 URL 解析器的结果。如果解析器返回失败,则返回
"Blocked"并中止后续步骤。 -
将 request 的 url 设置为 newURL。
注: 在导航前检查中,没有其他 CSP 指令会作用于
javascript:URL。其他检查 javascript: URL 的指令 稍后会在内联检查中作用于修改后的 URL。 -
返回
"Allowed"。
4.2.2. trusted-types 指令
本文档定义 trusted-types——一种新的内容安全策略 指令。trusted-types 指令控制可信类型 策略的创建。
directive-name = "trusted-types" directive-value = serialized-tt-configuration serialized-tt-configuration = ( tt-expression *( required-ascii-whitespace tt-expression ) ) tt-expression = tt-policy-name / tt-keyword / tt-wildcard tt-wildcard = "*" tt-policy-name = 1*( ALPHA / DIGIT / "-" / "#" / "=" / "_" / "/" / "@" / "." / "%") tt-keyword = "'allow-duplicates'" / "'none'"
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types one two
Content-Security-Policy: trusted-types; require-trusted-types-for 'script'
关键字 'none' 可用于显式表示上述内容:
关键字 'allow-duplicates' 允许创建名称已被使用过的策略。
如果列表中存在名为 default 的策略,则它指的是默认策略。
传递给注入
接收点的所有字符串都会先经过该策略,而不是被直接拒绝。
4.2.3. 接收点类型是否需要可信类型?
如果注入接收点需要可信类型,则此算法返回
true,否则返回 false。
接收点 类型是否需要可信类型?算法,给定一个全局对象(global)、一个字符串 (sinkGroup)和一个布尔值(includeReportOnlyPolicies),执行以下步骤:
-
对于 global 的 CSP 列表中的每个 policy:
-
如果 policy 的指令集不 包含一个指令, 且其名称为
"require-trusted-types-for",则跳到 下一个 policy。 -
令 directive 为 policy 的 directive set 中 名称为
"require-trusted-types-for"的指令 -
如果 directive 的值不包含与 sinkGroup 匹配的 trusted-types-sink-group,则跳到下一个 policy。
-
如果 policy 的处置为
"enforce",则令 enforced 为 true,否则为 false。 -
如果 enforced 为 true,则返回 true。
-
如果 includeReportOnlyPolicies 为 true,则返回 true。
-
-
返回 false。
4.2.4. 接收点类型不匹配违规是否应被内容安全 策略阻止?
如果注入接收点需要可信类型,则此算法返回
"Blocked",否则返回 "Allowed"。
接收点类型不匹配 违规是否应被内容安全策略阻止?算法,给定一个全局对象(global)、一个字符串(sink)、一个 字符串(sinkGroup)和一个字符串(source),执行以下步骤:
-
令 result 为
"Allowed"。 -
令 sample 为 source。
-
如果 sink 为
"Function",则:-
如果 sample 以
"function anonymous"开头,则从 sample 中移除它。 -
否则,如果 sample 以
"async function anonymous"开头,则从 sample 中移除它。 -
否则,如果 sample 以
"function* anonymous"开头,则从 sample 中移除它。 -
否则,如果 sample 以
"async function* anonymous"开头,则从 sample 中移除它。
-
-
对于 global 的 CSP 列表中的每个 policy:
-
如果 policy 的指令集不 包含一个指令, 且其名称为
"require-trusted-types-for",则跳到 下一个 policy。 -
令 directive 为 policy 的 directive set 中 名称为
"require-trusted-types-for"的指令 -
如果 directive 的值不包含与 sinkGroup 匹配的 trusted-types-sink-group,则跳到下一个 policy。
-
令 violation 为在 global、policy 和
"require-trusted-types-for"上执行 为全局对象、策略和指令创建 违规对象的结果。 -
将 violation 的资源设置为
"trusted-types-sink"。 -
令 trimmedSample 为 sample 的子字符串,包含其前 40 个字符。
-
将 violation 的样本设置为使用
"|"作为分隔符连接列表 « sink, trimmedSample « 所得的结果。 -
在 violation 上执行报告违规。
-
如果 policy 的处置为
"enforce",则将 result 设置为"Blocked"。
-
-
返回 result。
4.2.5. 可信类型策略创建是否应被内容安全 策略阻止?
如果不应创建 TrustedTypePolicy,
则此算法返回 "Blocked",否则返回 "Allowed"。
可信类型 策略创建是否应被内容安全策略阻止?算法,给定一个全局对象(global)、一个字符串 (policyName)和一个 字符串列表(createdPolicyNames),执行以下步骤:
-
令 result 为
"Allowed"。 -
对于 global 的 CSP 列表中的每个 policy:
-
令 createViolation 为 false。
-
如果 policy 的指令集不 包含一个指令, 且其名称为
"trusted-types",则跳到下一个 policy。 -
令 directive 为 policy 的 directive set 中 名称为
"trusted-types"的指令 -
如果 directive 的值仅包含一个与
'none'值匹配的tt-keyword,则将 createViolation 设置为 true。注: 与其他 CSP 指令一样, 如果存在其他关键字或策略名称,则会忽略 'none' 关键字。
-
如果 createdPolicyNames 包含 policyName,且 directive 的值不包含与
'allow-duplicates'值匹配的tt-keyword,则将 createViolation 设置为 true。注:
trusted-types policyA policyB 'allow-duplicates'允许作者创建 名称 重复的策略。 -
如果 directive 的值不包含值为 policyName 的tt-policy-name,且 directive 的值不包含 tt-wildcard,则将 createViolation 设置为 true。
注:
trusted-types *允许作者创建具有任意唯一名称的策略。要允许多个策略具有 相同名称,请使用trusted-types * 'allow-duplicates',或者完全不要设置trusted-types指令。 -
如果 createViolation 为 false,则跳到下一个 policy。
-
令 violation 为在 global、policy 和
"trusted-types"上执行 为全局对象、策略和指令创建 违规对象的结果。 -
将 violation 的资源设置为
"trusted-types-policy"。 -
将 violation 的样本设置为 policyName 的子字符串, 包含其前 40 个字符。
-
在 violation 上执行报告违规。
-
如果 policy 的处置为
"enforce",则将 result 设置为"Blocked"。
-
-
返回 result。
5. 安全注意事项
可信类型并非旨在保护对注入接收点的访问,使其免受 主动恶意执行环境的影响。这里假定应用程序由 非恶意作者编写;其目的是防止开发者错误 导致安全漏洞,而不是防御主动试图 绕过策略限制的第一方恶意代码。下面列出了 已经识别出的、即使在强制执行 可信类型的环境中仍然存在风险的向量。
5.1. 跨文档向量
虽然在强制执行可信类型的窗口中运行的代码无法
动态创建会绕过策略限制的节点,但
此类节点仍可能从其他
窗口中不具有同一组限制的文档导入或采用。实质上——
如果恶意作者创建一种受限文档与
不受限文档串通的设置,就可能绕过可信类型。在极端情况下,
受限文档可能会从字符串创建一个 Blob
并导航到它。
CSP 传播规则(参见 内容安全
策略 3 § 7.8 继承 CSP 以避免绕过)部分解决了这一
问题,因为新的本地方案文档将继承同一组限制,
因此——例如——可以使用 script-src 限制来确保注入
Blob
内容不会执行脚本。要全面解决此问题,
应使用其他机制,例如 源策略,
以确保将基准安全规则应用于整个
源。
5.2. 已弃用功能
一些长期弃用且很少使用的平台功能不受可信 类型约束,恶意作者可能利用这些功能绕过 限制:
5.3. 脚本 gadget
虽然可信类型逻辑会在许多由字符串创建 DOM 树的操作上调用,但不应将其视为保护文档中所有 DOM 树创建的机制。这一点尤其在存在 脚本 gadget 时非常重要,其中应用程序会对通常无害的 DOM 元素或属性内容作出反应。 直接使用 DOM API 的开发者可以在不使用 可信类型的情况下触发此类 gadget。不过,要让 gadget 触发 DOM XSS,它需要 通过策略获得可信类型值。如果策略规则本身没有 强制约束或验证数据,作者需要确保传递给可信类型策略的数据 确实可信。
5.4. 策略设计最佳实践
可信类型将能够通过注入 接收点引入漏洞的代码范围限制到策略的实现。 在这种设计中,不安全的策略仍然可能使注入接收点暴露于不可信数据。 使用策略时需要特别注意:策略要么对所有 可能的输入都是安全的,要么限制对不安全策略的访问,使其仅 使用非攻击者控制的输入调用。
由于策略是自定义 JavaScript 代码,因此可能被编写为严重 依赖全局状态。我们不建议这样做。策略应 尽可能自包含。任何可能改变 策略所作安全决策的对象实际上都会成为策略的一部分,应当一起保护和审查。
如果 createParserOptions
回调返回的配置未移除不安全标记(例如脚本或事件处理器),
则无法防止 DOM XSS。
策略作者还应仔细检查传递给
createParserOptions
的 argument["sanitizer"] 中由调用者提供的任何净化器。
盲目信任或直接传递调用者的净化器,会使未经审查的配置控制解析。
因为 createParserOptions
即使在输入标记已经是现有 TrustedHTML
实例时仍会执行,
默认策略可以确保未经审查的调用者选项无法绕过应用程序范围的净化或
脚本执行约束。
如果没有这样的回调,TrustedHTML
就不能与调用者提供的非空净化器或设置为 true 的 runScripts 组合使用,因为
这些选项可能使已经审查过的标记变得不安全。
6. 隐私注意事项
本规范可能会部分观察和改变在 应用程序内运行的脚本行为,例如使对注入接收点的某些操作 失败,或者使用默认策略 监控和更改这些操作的效果。 不过,较早运行的脚本已经可以通过覆盖 相应的属性描述符获得这种能力。
应用程序可以报告违反可信类型 限制的行为。违规报告将包括传递给 注入接收点的截短载荷(40 个字符,包括接收点名称)。此功能 复用了内容安全策略的报告机制。
7. 实现注意事项
7.1. 供应商特定的扩展和附加组件
可信类型施加的限制不应 干扰用户代理功能(例如附加组件、 扩展或书签脚本)的运行。这些类型的功能通常体现 用户优先于页面作者的原则,如 [html-design-principles] 所倡导的那样。具体而言,扩展应能够 将字符串 传递给注入接收点, 而不会触发默认策略 执行、生成违规或拒绝该值。