1. 简介
本文档定义了文档策略,它是一个用于设计 Web 平台中可配置功能的框架,并允许 Web 开发者在其网站部署过程中配置这些功能。
2. 示例 #
需要新的示例。目前请参见说明文档。
3. 其他和相关机制
文档策略与一些现有的文档配置机制在范围上类似,不过与每个机制都有显著区别。
3.1. 与权限策略的关系
权限策略 [PERMISSIONS-POLICY] 是另一种允许作者配置文档中功能的机制, 虽然范围类似,但它使用了不同的继承机制,使其更适合某些类型的功能, 这些功能不同于适合由文档策略控制的功能。
历史上,文档策略是作为对权限策略(当时称为功能策略)中一些提议功能添加的响应而创建的, 这些功能要么不完全符合现有的“功能”模型,要么需要向权限策略规范添加大量额外复杂性。 这包括带参数的功能、可选择继承到子框架中的功能,以及在弹出窗口中与其他顶层浏览上下文具有不同继承方式的功能。
这些功能现在被提议由文档策略覆盖,而权限策略用于委派是主要关注点的功能。 权限策略功能具有布尔值(启用或禁用),如果在父框架中禁用,则永远不能在子框架中重新启用, 并且通常遵循以下模型:“在顶层浏览上下文及其同源子上下文中可用;必须委派给跨源框架”。
相比之下,由文档策略控制的功能可以接受参数,并且这些参数可以在不同框架中具有互不相关的值 (在父框架中约束某个功能并不一定会约束其子框架)。
3.2. 与内容安全策略的关系
内容安全策略 [CSP] 也会配置文档中的“功能”, 尽管它主要关注页面中资源的来源,而不是控制这些资源加载后可以执行的操作。
CSP 还通过 sandbox 指令提供了为文档设置沙箱标志的另一种机制。 如果沙箱标志被迁移到文档策略中,那么这可能是冗余的,因为两个标头可能编码相同的信息。
CSP-Embedded-Enforcement 引入了一种模型,用于强制子文档遵守某个策略, 并在 Fetch 期间将不符合要求的文档作为网络错误拒绝。该模型被文档策略用于必需策略机制。
3.3. 与沙箱的关系
iframe 沙箱是另一种控制文档中功能的机制,其行为方式与文档策略的必需策略非常相似: 禁用某个功能可以施加到框架上,并影响加载到该框架中的所有内容。
iframe 沙箱属性所控制的功能可以非常自然地通过文档策略表达。
iframe 沙箱与文档策略之间的一个关键区别是,当在框架上使用 “sandbox” 属性时, 所有沙箱功能默认都会被应用,并且必须逐一重新启用。这使得扩展沙箱模型以支持新功能非常困难, 因为任何新增内容都会立即影响所有现有沙箱内容。此外,源服务器没有机制知道其内容将被沙箱化, 因此很难添加可能改变沙箱文档控制流的新沙箱功能,因为这可能会在现有内容中引入新的安全漏洞。
4. 框架
4.1. 配置点
一个配置点是一个 Web 平台 API 或行为, 可以通过文档策略启用、禁用或配置。 配置点应在描述底层 API 或行为的规范中定义,尽管本文档附带了一个正在使用的已定义配置点注册表。
一个配置点 具有一个类型,它是以下之一:
-
boolean, -
integer, -
float,或 -
enum。
4.2. 策略
一个策略配置 是一个元组,由一个值组成,该值是 配置点 的范围中的元素,以及一个 报告端点组成,该端点是一个字符串, 并且可以为 null。
一个浏览上下文具有一个必需文档策略, 它是一个文档策略。 一个具有 null 打开者浏览上下文的浏览上下文具有一个空的 必需文档策略。
一个Document具有一个嵌套上下文必需文档策略, 它是一个文档策略。
5. 必需策略序列化
-
在此说明如何将必需策略作为结构化标头进行序列化。
-
确保存在一种规范形式(用于兼容性测试)。
6. 报告
部署文档策略的网站可能希望知道其页面上设置的任何策略是否被违反。例如,一个设置要求所有图像
匹配其容器大小的策略的网站,可能希望在新开发者或 CMS 将超大图像插入内容时收到提醒。
类似地,一个部署限制使用 document.write API 的策略的网站,可能希望在某个脚本被导入
且使用该 API 时接收报告。
本节定义了使用报告 API 报告此类违规行为的机制。 [REPORTING]
网站也可能希望在实际强制执行策略之前,在真实环境中测试该策略。 本节还定义了“仅报告”模式,在该模式下,用户代理可以观察会导致策略违规的情况并报告它们, 而不会强制执行该策略。这使网站所有者可以在实际部署策略之前,将真实环境中的违规数量降低到可接受水平。
报告只能从配置策略的页面发出。无法从违反必需策略的嵌套页面接收报告。
“违规”按功能定义,但始终应反映 Web 开发者的操作,而不是用户直接执行的操作。
这意味着并非所有策略都可以进行报告。有一类功能,其设置无法通过标记或脚本操作以有意义的方式被称为“违规”。 例如,一个假设的禁用表单字段文本输入的功能,可以由用户代理强制执行, 但如果用户尝试在这些字段中输入文本,从而需要进行强制执行,这并不表示违反策略,也不应进行报告。
6.1. 配置文档内报告
6.1.1. “report-to”参数
任何指令都可以包含一个名为 report-to 的参数,该参数指定一个
端点,功能违规报告将发送到该端点。
示例:
Document-Policy: something=1.0;report-to=endpoint1, something-else=?0;report-to=endpoint2
6.1.2. 设置默认报告端点
如果许多或所有功能的违规报告都应发送到同一个端点,
那么定义单个默认端点可能更方便。
这可以通过特殊token
*上的参数进行定义。如果提供了默认
端点,那么除非另有指定,所有违规报告都会发送到该命名端点。
如果某个功能还通过 report-to 参数指定了自己的端点,
那么报告将发送到该端点。(报告不会同时发送到两个端点。)
示例:
Document-Policy: something=1.0, something-else=?0, *;report-to=endpoint
6.1.3. 禁用功能的报告
如果已指定默认端点,则可能需要针对特定功能禁用报告。
这可以通过将特殊端点名称 none 指定为 report-to 参数的值来实现。
这将覆盖默认端点,并禁用该功能的报告。
示例:
Document-Policy: something=1.0;report-to=none, something-else=?0,
*;report-to=endpoint
6.2. 仅报告模式
文档策略可以是“仅报告”策略。仅报告策略通过
Document-Policy-Report-Only 标头指定。仅报告策略的违规行为会像强制执行策略一样
生成报告,但不会导致用户代理采取任何其他操作。
Document-Policy-Report-Only
应将 report-to 指令参数与此标头中的指令一起使用,否则它们将完全不起作用。
示例:
Document-Policy-Report-Only: something=1.0;report-to=endpoint,
something-else=?0;report-to=endpoint2
7. 交付
7.1. 作为结构化标头的策略
策略在 HTTP 标头和 HTML 属性中表示为 sf-dictionary 结构的序列化。每个字典成员都是一个 文档策略指令。
一个文档策略指令 是序列化文档策略的一个元素, 由一个指令名称组成, 该名称是一个 sf-token, 以及关联的参数。
一个指令名称可以是以下之一:
7.1.1. 参数
任何文档策略指令都可以包含一个名为
report-to 的参数,
其值必须是一个
token。
一个文档策略指令,
其指令名称指定了一个
配置点,
其类型为
boolean,没有必需参数。
一个文档策略指令,
其指令名称指定了一个
配置点,
其类型为
integer,具有一个必需参数,
其值必须是该配置点
范围中的整数。
一个文档策略指令,
其指令名称指定了一个
配置点,
其类型为
float,具有一个必需参数,
其值必须是该配置点
范围中的十进制数。
一个文档策略指令,
其指令名称指定了一个
配置点,
其类型为
enum,具有一个必需参数,
其值必须为 true,
并且其名称必须是该配置点
范围中的
token。
示例:
-
boolean-feature -
boolean-feature=?0 -
integer-feature=2 -
float-feature=-0.2 -
enum-feature=state
7.2. HTTP 标头
7.2.1. Document-Policy
The `Document-Policy` HTTP
标头可以在响应(服务器到客户端)中使用,以传递客户端应强制执行的
文档
策略。
Document-Policy 标头是一个结构化标头。其值
必须是一个字典。其 ABNF 为:
Document-Policy = sf-dictionary
如果任何字典成员名称不是受支持配置点的名称, 或不是特殊值 "*",则该字典成员将在处理步骤中被忽略。
7.2.2. Document-Policy-Report-Only
The `Document-Policy-Report-Only`
HTTP 标头可以在响应(服务器到客户端)中使用,以配置该文档的
仅报告文档策略。
Document-Policy-Report-Only 标头是一个结构化标头。
其值必须是一个字典。它与
Document-Policy 标头具有完全相同的语法。
7.2.3. Require-Document-Policy
The `Require-Document-Policy`
HTTP 标头字段是一个响应标头,用于向客户端传递应用于所有嵌套内容的最低
必需文档策略。
Require-Document-Policy 标头是一个结构化标头字典,
具有与 Document-Policy 标头完全相同的语法。
7.2.4. Sec-Required-Document-Policy
The `Sec-Required-Document-Policy`
HTTP 标头字段是一个请求标头,用于向服务器传递
文档策略,
该策略必须与请求返回的文档一起发送。
该标头的值是一个或多个 文档策略指令 的§ 5 必需策略序列化。
7.3.
iframe 元素的 policy
属性
iframe
元素具有一个 "policy" 属性,其中包含一个必需策略指令(SH 格式)。
8. 集成
如果一个框架具有必需策略,则该策略必须在任何传出的文档请求的请求标头中声明, 以告知服务器用户代理将应用于文档的策略。这使服务器可以修改返回的表示形式, 使其符合该策略。
如果存在必需策略请求标头,则响应必须包含兼容的文档策略标头,否则 Fetch 将失败。
8.1. 与 HTML 集成
以下更改应纳入 [HTML]:
-
iframe元素应添加以下 IDL:
[CEReactions] attribute DOMString policy;
-
iframe policy 属性应定义如下:
-
在 HTML § 3.1.1 Document 对象中,添加以下内容:
-
在创建新的浏览上下文 算法中:
-
在第 5 步之后添加以下步骤:
-
将 browsingContext 的 必需文档策略 设置为对 browsingContext 执行 为浏览上下文创建必需策略 的结果。
-
-
将第 9 步(现在重新编号为第 10 步)修改为:
-
-
在处理导航 Fetch 算法中:
-
在初始化 document 对象 算法中:
-
在第 3 步之后添加以下步骤:
-
将第 6 步(现在重新编号为第 8 步)修改为:
-
令 document 为新的 Document,其类型为 type, 内容类型为 contentType, origin 为 origin, 权限策略为 permissionsPolicy, 活跃沙箱标志集为 finalSandboxFlags, 文档策略为 documentPolicy, 嵌套上下文必需文档策略为 nestedContextRequiredDocumentPolicy。
-
-
8.2. 与 Fetch 集成
以下更改应纳入 [FETCH]:
-
在 Fetch § 2.2.5 请求 中,添加以下内容:
-
在 Fetch § 4.6 HTTP-network-or-cache fetch 中,在第 15 步之后插入以下内容:
-
在 Fetch § 4.1 Main fetch 中,在第 11 步的算法列表中添加以下算法:
9. 算法
9.1. 策略是否兼容?
-
对于 requiredPolicy 中的每个 configuration point → value:
-
如果 declaredPolicy[configuration point] 不存在, 则返回 false。
-
如果 value 比 declaredPolicy[configuration point] 更严格, 则返回 false。
-
-
返回 true。
9.2. 解析文档策略
-
如果 header 为 null,则返回 null。
-
令 policy 为一个新的有序映射。
-
令 defaultEndpoint 为一个新的字符串,并设置为 null。
-
对于 header 中的每个 name->(value,parameters):
-
令 currentEndpoint 为一个新的字符串,并设置为 null。
-
如果 parameters["report-to"] 存在,并且是一个 token,则:
-
将 currentEndpoint 设置为 parameters["report-to"] 的值。
-
-
如果 name 是字符串 "
*",则:-
将 defaultEndpoint 设置为 currentEndpoint。
-
-
否则,如果 name 是受支持配置点的名称,则:
-
令 configuration point 为名称为 name 的受支持配置点。
-
如果 policy[configuration point] 存在, 则继续处理下一个 element。
-
如果 configuration point 的类型为 boolean,则:
-
如果 configuration point 的类型为 enum,则:
-
如果 configuration point 的类型为 integer,则:
-
如果 configuration point 的类型为 float,则:
-
-
-
对于 policy 中的每个 configuration point → config:
-
返回 policy。
9.3. 序列化必需策略
-
令 dict 为一个新的有序映射。
-
令 features 为 requiredPolicy 的键。
-
按照 ASCII 顺序,根据每个元素的名称对 features 进行排序。
-
对于 features 中的每个 feature:
-
令 value 为 requiredPolicy[feature]。
-
将 dict[feature] 设置为 value。
-
-
返回 dict 的序列化结果。
9.4. 为浏览上下文创建必需策略
-
如果 browsingContext 是一个嵌套浏览上下文,则
-
令 requiredPolicy 为 browsingContext 的 容器文档的 嵌套上下文必需文档策略 的克隆。
-
如果 browsingContext 的 浏览上下文容器 具有一个 "policy" 属性,则
-
令 containerPolicy 为解析该属性的结果。
-
对于 containerPolicy 中的每个 feature -> value:
-
如果 requiredPolicy[feature] 不存在, 或者 value 比 requiredPolicy[feature] 更严格, 则将 requiredPolicy[feature] 设置为 value。
-
-
-
-
否则,令 requiredPolicy 为一个新的有序映射。
-
返回 requiredPolicy。
9.5. 从响应创建文档策略
-
令 requiredPolicy 为在给定 browsingContext 上运行 为浏览上下文创建必需策略 的结果。
-
令 header 为从 response 的 标头列表中, 使用标头名称
Document-Policy和类型 "dictionary" 调用 获取结构化字段值 的结果。 -
令 declaredPolicy 为对 header 执行 解析文档策略 的结果。
-
如果 declaredPolicy 与 requiredPolicy 兼容, 则返回 declaredPolicy。
-
抛出异常。
9.6. 从响应创建嵌套上下文必需文档策略
-
令 requiredPolicy 为 browsingContext 的 必需文档策略的克隆。
-
令 header 为从 response 的 标头列表中, 使用标头名称
Required-Document-Policy和类型 "dictionary" 调用获取结构化字段值的结果。 -
令 declaredNestedPolicy 为对 header 执行 解析文档策略 的结果。
-
对于 declaredNestedPolicy 中的每个 feature -> value:
-
如果 requiredPolicy[feature] 不存在, 或者 value 比 requiredPolicy[feature] 更严格, 则将 requiredPolicy[feature] 设置为 value。
-
-
返回 requiredPolicy。
9.7. 响应是否应因文档策略而被阻止?
9.8. 获取文档中功能的策略值
Document
对象(document),此算法返回
document 的文档策略
中 feature 的值。
-
令 policy 为 document 的 Document Policy。
-
如果 policy[feature] 存在,则返回其 值。
-
返回 feature 的 默认值。
9.9. 确定值与功能策略的兼容性
Document
对象(document),此算法返回一个由以下内容组成的元组:
-
一个操作,根据 value 是否与 document 的 文档策略 兼容,取值为 "compatible" 或 "incompatible",
-
一个报告端点名称,如果 value 同时与 document 的 文档策略 和其 仅报告文档策略 兼容,或者没有为 feature 配置报告,则该值为 null; 否则该值为应发送违规报告的 报告端点 的名称。
注意,如果强制执行策略比仅报告策略更严格,则不会检查仅报告策略。
-
令 policy 为 document 的 Document Policy。
-
令 policyConfig 为 policy[feature](如果存在), 否则为由 feature 的 默认值 和 null 组成的元组。
-
令 policyValue 和 reporting endpoint 为 policyConfig 的元素。
-
如果 policyValue 比 value 更严格,则返回由 "incompatible" 和 reporting endpoint 组成的元组。
-
令 report-only policy 为 document 的 仅报告文档策略。
-
令 report-only policyConfig 为 report-only policy[feature](如果存在), 否则为由 feature 的 默认值 和 null 组成的元组。
-
将 policyValue 和 reporting endpoint 设置为 report-only policyConfig 的元素。
-
如果 policyValue 比 value 更严格,则返回由 "compatible" 和 reporting endpoint 组成的元组。
-
返回 ("compatible", null)。
9.10. 确定值是否与功能策略兼容或报告
Document
对象(document),如果 value 与
document 的
文档策略
兼容,则此算法返回 "compatible",否则返回 "incompatible"。
如果已配置报告,它还会排队生成报告。
-
令 (action, reporting endpoint) 为使用 value、feature 和 document 调用 确定兼容性 的结果。
-
如果 reporting endpoint 不为 null,则
-
令 body 为具有以下属性的新 ECMAScript 对象: [ECMA-262]
- featureId
-
功能的字符串表示形式。
- sourceFile
-
null
- lineNumber
-
null
- columnNumber
-
null
- disposition
-
如果 action 为 "incompatible",则为 "enforce"; 否则为 "report"。
-
如果用户代理当前正在执行脚本,并且可以从设置中提取源文件 URL、 行号和列号,则相应地设置 body 的 sourceFile、lineNumber 和 columnNumber。
-
令 settings 为 document 的 环境设置对象。
-
使用 body、"document-policy-violation"、 reporting endpoint 和 settings 执行 Reporting API § 2.3 将数据作为类型排队到目标。
-
-
返回 action。
9.11. 确定值是否与功能策略兼容
10. IANA 注意事项
永久消息标头字段注册表应使用以下注册项进行更新 [RFC3864]:
- 标头字段名称
- Document-Policy
- 适用协议
- http
- 状态
- standard
- 作者/变更控制者
- W3C
- 规范文档
- Document Policy API
- 标头字段名称
- Require-Document-Policy
- 适用协议
- http
- 状态
- standard
- 作者/变更控制者
- W3C
- 规范文档
- Document Policy API
- 标头字段名称
- Sec-Required-Document-Policy
- 适用协议
- http
- 状态
- standard
- 作者/变更控制者
- W3C
- 规范文档
- Document Policy API
11. 隐私和安全
本规范标准化了一种机制,使嵌入页面可以设置一个将在嵌入页面上强制执行的策略。
与现有的 iframe
sandbox
机制不同,必需策略需要显式确认。这意味着,如果没有这些网站的配合,
已发布网站中现有功能的行为不能被更改。
使用此模型时,需要考虑一些隐私和安全事项:
-
将跨源子框架中的行为暴露给其嵌入者。
-
通过策略将嵌入者状态暴露给嵌入文档。
-
盲目接受必需策略导致的意外行为变化。
在一定程度上,这些问题已经存在于 Web 平台中,本规范至少尝试避免使这些问题变得不必要地严重。
安全和隐私问题也可能由单独配置点的设计引起,因此在与本规范集成时必须谨慎。 本节尝试提供有关哪些类型的行为可能导致此类问题的指导。
11.1. 跨源行为的暴露
配置点的设计应确保框架文档中的策略违规不会被其他框架中的文档观察到。 例如,假设存在一个功能:当该功能被策略禁用时使用,会导致嵌入文档触发事件, 那么该功能可能被用于提取有关嵌入文档状态的信息。如果某个功能仅在用户登录网站时使用, 例如,嵌入者可以为框架禁用该功能,然后监听由此产生的事件,以确定用户是否已登录。
此外,必须注意不要通过策略使跨源资源内容的信息(通常文档无法访问这些信息)变得可见。 例如,图像内容可能包含私人信息,而细粒度策略可能允许攻击者通过仔细调整策略配置参数, 推断图像内容中的某些信息。作用于子资源内容的策略应排除不可读取的资源, 或采取措施限制可以推断出的资源信息量。
11.2. 必需策略的声明
作为对上述行为变化问题的缓解措施,具有必需策略的框架中的嵌入内容请求将携带一个 HTTP 标头, 详细说明策略要求。该标头对源服务器可见,其内容可能会泄露有关嵌入页面的详细信息。 嵌入者在选择对其嵌入内容要求策略时应注意这一点。
11.3. 盲目接受必需策略
由于遵守嵌入者要求的策略是被加载的必要条件,网站所有者可能会尝试配置 Web 服务器,
直接将响应中的 Document-Policy 标头设置为回显
Sec-Required-Document-Policy 请求标头。
虽然这样可以确保文档策略始终与请求兼容,但它可能使嵌入文档面临风险:
嵌入者可以通过禁用或改变现有 API 的行为来改变其中的控制流。
当内容编写完成后,文档策略模型中又添加新的配置点时,这种风险尤其明显。
要使文档能够抵御所有可能的新行为变化是困难的。
预计会被嵌入到具有必需文档策略上下文中的网站,可以通过将其策略设置为它们已知能够支持的实际最严格策略, 或者仅对它们了解并理解潜在行为变化范围的配置点回显传入策略,来降低这种风险。