权限策略

W3C 工作草案,

关于本文档的更多详情
本版本:
https://www.w3.org/TR/2025/WD-permissions-policy-1-20251006/
最新发布版本:
https://www.w3.org/TR/permissions-policy/
编辑草案:
https://w3c.github.io/webappsec-permissions-policy/
先前版本:
历史记录:
https://www.w3.org/standards/history/permissions-policy-1/
反馈:
GitHub
规范内反馈
编辑:
(Google)

摘要

本规范定义了一种机制,允许开发者有选择地启用或禁用各种浏览器特性和 API 的使用。

本文档状态

本节描述了本文档在发布时的状态。当前 W3C 出版物列表及本技术报告的最新修订版可在 W3C 技术报告索引中找到。

本文档由 Web 应用安全工作组推荐标准流程 发布为工作草案。本文档旨在成为 W3C 推荐标准。

(存档) 公共邮件列表 public-webappsec@w3.org (参见说明) 是讨论本规范的首选渠道。 发送邮件时,请在主题中注明“permissions-policy”, 建议如下格式:“[permissions-policy] …评论摘要…

作为工作草案发布并不意味着 W3C 及其成员的认可。本文档为草案,可能随时更新、替换或废止。将本文档作为正式内容引用是不合适的,应视为正在进行中的工作。

本文档由 Web 应用安全工作组制作。

本文档由遵守 W3C 专利政策的团队制作。W3C 维护了一个公开专利披露列表,其中记录了与工作组交付物相关的专利披露;该页面还包含专利披露的说明。知晓某专利并认为其包含必要声明的个人,须根据W3C 专利政策第6节进行披露。

本文档受 2025年8月18日 W3C 流程文件约束。

1. 简介

Web 平台不断扩展功能和 API,提供更丰富的功能、更好的开发者体验和更高的性能。但开发者在应用内选择性地启用、禁用或修改部分浏览器功能和 API 的行为,仍然缺乏机制:

  1. 开发者可能希望选择性地禁用某些浏览器功能和 API,以“锁定”应用,作为安全或性能预防措施,防止自身或第三方内容在应用中执行时引入不期望或意外行为。
  2. 开发者可能希望选择性地启用某些默认禁用的浏览器功能和 API。例如某些功能在嵌入上下文中默认禁用,除非明确启用;有些功能还可能受其他策略要求约束。
  3. 开发者可能希望用策略向客户端或嵌入方声明有关某些功能和 API 的使用或不使用承诺。例如启用某些类型的浏览器“快速路径”优化,或声明符合其他嵌入方(如社交网络、搜索引擎等)的某些要求。

本规范定义了一种策略机制,解决上述使用场景。

本规范原名为 Feature Policy(特性策略)。

2. 示例

SecureCorp 公司希望禁用其应用中的全屏和地理定位 API。可以通过发送如下 HTTP 响应头定义权限策略:

Permissions-Policy: fullscreen=(), geolocation=()

指定空的来源列表后,相关功能将对所有文档(包括嵌套文档)禁用,无论其来源如何。

地理定位在所有跨域框架中默认禁用。FastCorp 公司有一个特定的跨域 iframe 需要启用地理定位。可以在 iframe 元素上添加 "allow" 属性实现:

<iframe src="https://other.com/map" allow="geolocation"></iframe>

iframe 属性可以选择性地为某些框架启用功能,而不是全部,即使这些框架包含来自同一来源的文档。

SecureCorp 公司希望完全禁用除自身来源和 "https://example.com" 来源外的所有后代可导航对象的地理定位 API,即使攻击者能在 SecureCorp 页面嵌入自己的 iframe。可以通过如下 HTTP 响应头为地理定位定义受限权限策略:

Permissions-Policy: geolocation=(self "https://example.com")

允许名单是一组包含一个或多个来源的列表,可包含应用自身来源(可用 "self" 关键字表示)以及任何第三方来源。

启用此策略后,仍可通过 iframe 的 "allow" 属性为特定框架授权地理定位,但只有托管来自 http://example.com 或 SecureCorp 本身内容的框架才会实际获得该 API 的使用权限。

SecureCorp 公司重组域名,现在需要将地理定位 API 的使用授权给其自身来源 ("https://example.com") 及三个子域名 ("https://geo.example.com"、"https://geo2.example.com" 和 "https://new.geo2.example.com"),同时应禁用所有其他浏览上下文的地理定位 API。可以通过如下 HTTP 响应头实现:

Permissions-Policy: geolocation=(self "https://example.com" "https://geo.example.com" "https://geo2.example.com" "https://new.geo2.example.com")

如果 SecureCorp 公司认可授权给 "https://example.com" 的任何子域,则可以用如下 HTTP 响应头:

Permissions-Policy: geolocation=(self "https://example.com" "https://*.example.com")

上述头部不仅允许 "https://geo.example.com"、"https://geo2.example.com" 和 "https://new.geo2.example.com" 使用地理定位 API,也允许 "https://example.com" 的其他所有子域使用。注意 "https://example.com" 并不包含在 允许名单项 "https://*.example.com" 中,需单独添加。

SecureCorp 公司重组服务,现在需要将地理定位 API 的使用授权给其自身来源 ("https://example.com") 及三个非默认端口 ("https://example.com:444"、"https://example.com:445" 和 "https://example.com:446"),同时应禁用所有其他浏览上下文的地理定位 API。可以通过如下 HTTP 响应头实现:

Permissions-Policy: geolocation=(self "https://example.com" "https://example.com:444" "https://example.com:445" "https://example.com:446")

如果 SecureCorp 公司认可授权给 "https://example.com" 的所有端口,则可以用如下 HTTP 响应头:

Permissions-Policy: geolocation=(self "https://example.com:*")

上述头部不仅允许 "https://example.com:444"、"https://example.com:444" 和 "https://example.com:445" 使用地理定位 API,也允许 "https://example.com" 的其他端口使用。

JSPlaygroundCorp 公司希望托管用户生成的 Web 应用,但希望浏览器能将这些应用对强大功能的权限彼此隔离。可以为每个 Web 内容或内容创作者创建独立子域,并将其作为顶级文档导航(框架和用户内容仍可用同源 iframe 分离)。

这是因为用户在浏览器中授予权限是针对他们认为在交互的顶级域名。

JSPlaygroundCorp 在此场景下应避免使用自身域名通过 allow 属性 iframe 用户生成的 Web 应用,否则会给予自身域名所有权限。

PlatformCorp 公司希望在其顶级域名下提供可嵌入第三方组件的市场,包括游戏。希望合理授权强大功能getUserMedia() API,并承担追踪哪些组件应用需要某项功能的责任,通过定制化“安装”界面让终端用户掌控权限。

摄像头和麦克风在所有跨域框架中默认禁用。每个第三方组件有各自的子域,可用跨域 iframe 嵌入。PlatformCorp 可以在 allow 属性或 iframe 元素上控制是否授权每个子域摄像头或麦克风访问。

如果组件 "app1" 需摄像头权限,"app2" 需麦克风权限,"app3" 需两者,iframe 可如下:

<iframe
  allow="camera https://app1.site.com https://app3.site.com;
         microphone https://app2.site.com https://app3.site.com"
  src="https://doc1.site.com"
  sandbox="allow-same-origin allow-scripts">
</iframe>

iframe 属性可选择性地为某些框架启用功能,而不是全部,即使这些框架来自同源。沙箱令牌列表在实际应用中可能更长。

由于浏览器通常要求用户对顶级域名授权,组件请求摄像头或麦克风权限时,如果用户已信任 PlatformCorp,可能不会有额外的权限提示。

[HTML5] 定义了 sandbox 属性用于 iframe 元素,允许开发者通过施加限制降低引入潜在不可信内容的风险——比如禁止提交表单、运行脚本和插件等。由 sandbox 指令定义的 [CSP2] 将此能力扩展到任意资源,无论是否被框架包裹,都可以要求同样的限制——比如通过 HTTP 响应头 (Content-Security-Policy: sandbox)。这些机制使开发者可以:

但上述机制存在一些局限:开发者无法自动为所有上下文应用策略,这使得在某些场景(如第三方内容注入框架且开发者无法控制时)难以或无法一致强制执行;没有机制选择性启用默认关闭的功能;沙箱机制会自动禁用所有沙箱特性,开发者需要逐项选择恢复,因此扩展沙箱特性集存在重大兼容风险。

权限策略旨在与沙箱机制结合使用(不会重复沙箱已涵盖的特性控制),并提供可扩展机制以解决上述局限。

4. 框架

4.1. 策略控制的特性

策略控制的特性是一种可通过权限策略在文档中启用或禁用的 API 或行为。

为简略起见,本文档通常将策略控制的特性简称“特性”。除非另有说明,“特性”指策略控制的特性。定义此类特性的其他规范应使用完整术语,以避免歧义。
本规范目前仅涉及文档中定义的特性。我们应考虑如何表述,以包含 Worker 和 Worklet 中的特性与权限策略。

策略控制的特性通过令牌标识,即在策略指令中使用的字符串。

每个策略控制的特性都有一个默认允许名单,定义该特性在顶级可遍历文档中的可用性,以及在子可导航对象中如何继承访问权限。

用户代理拥有一组已支持特性,即可通过策略控制的特性集合。用户代理不要求支持每一个特性

策略控制的特性本身并不属于本框架。当前已定义特性的非规范性列表,维护在本规范配套的 伴随文档中。

4.2. 策略

声明的策略是一个结构体,包含如下

声明

一个有序映射,从特性允许名单

报告配置

一个有序映射,从特性字符串

权限策略是一个结构体,包含如下

继承策略

一个有序映射,从特性 到"Enabled"或"Disabled"

声明的策略

一个声明的策略

空权限策略是一个权限策略,其继承策略在每个已支持特性上都包含"Enabled",其声明的策略声明报告配置均为空有序映射

4.3. 继承策略

特性的继承策略feature继承策略中以feature为键的值。在权限策略初始化后,其继承策略会包含每个已支持特性的值。

在创建和导航时,每个 Document 都会从父框架继承一组策略,若是 Document顶级可遍历对象中,则继承每个策略控制的特性的默认值。此继承策略决定每个特性的初始状态("Enabled"或"Disabled"),以及是否可由 声明的策略Document 中控制。

对于 Document顶级可遍历对象中,继承策略基于每个特性的默认值。

对于 Document子可导航对象中,继承策略基于父文档的权限策略以及子可导航对象容器策略

4.4. 头部策略

头部策略 是通过 HTTP 头与文档一起传递的一组策略指令。 它构成了文档的权限策略声明策略

4.5. 容器策略

除了头部策略外,每个 子可导航对象 都有一个容器策略, 它是一个策略指令,可以为空。 容器策略可以通过 可导航容器上的属性进行设置。

容器策略对于 子可导航对象 会影响加载到该可导航对象中的任何Document继承策略。 (参见 第9.7节 在容器中为来源定义特性的继承策略)。

当前,容器策略不能直接设置,而是间接通过 iframeallowfullscreenallow 属性设置。 未来本规范可能会新增机制,以显式声明完整的容器策略

4.6. 策略指令

策略指令 是一个有序映射, 将策略控制的特性 映射到对应的允许名单

策略指令 在 HTTP 头中以 sf-dictionary 结构序列化表示,在 HTML 属性中则为其 ASCII 序列化。

4.7. 允许名单

权限策略中的允许名单 在概念上是一组来源。 一个允许名单可以是:

  • 特殊值 * ,代表所有来源,或
  • 一个结构,包含:
关键词 'self''src''none' 可出现在允许名单的头部和属性字符串表示中。 这些关键词在解析时始终按上下文解释,仅其所指的来源会存储在允许名单中,关键词本身不在允许名单里。

要判断允许名单 是否匹配某个来源 origin,请执行如下步骤:

  1. 如果允许名单特殊值 *, 则返回 true。

注意:未采用 CSP 的通配符匹配方案,因为其要求 HTTPS 协议。

  1. 如果允许名单自身来源不为 null, 且与origin同源域,则返回 true。

  2. 如果允许名单src来源不为 null, 且与origin同源域,则返回 true。

  3. 如果origin是一个不透明来源,则返回 false。

  4. url为调用url 解析器 处理origin序列化结果。

  5. 对每个 权限来源表达式 item允许名单表达式中:

    1. 如果运行URL 是否与来源表达式匹配(含重定向计数) (参数为urlitemorigin和0)结果为 true,则返回 true。

  6. 返回 false。

4.8. 默认允许名单

每个策略控制的特性 都有一个默认允许名单默认允许名单 决定了在没有声明策略Document 中以及在顶级可遍历对象 时该特性是否允许,以及是否自动授权给子可导航对象中的文档。

默认允许名单 的可能取值有:

*
该特性在顶级可遍历对象中的 Document 及所有子可导航对象中默认允许。 可通过在可导航容器上显式指定 容器策略来禁用该特性, 或者通过为任意可导航对象 提供合适的Permissions-Policy头部实现禁用。
'self'
该特性在顶级可遍历对象中的 文档, 以及子可导航对象文档与其 父对象文档同源时默认允许, 且父文档允许该特性。在子可导航对象中, 文档父对象文档为跨域时默认不允许。

5. 权限策略序列化

5.1. HTML 属性序列化

策略指令 在 HTML 属性中以其 ASCII 序列化形式表示,ABNF 如下:

serialized-permissions-policy = serialized-policy-directive *(";" serialized-policy-directive)
serialized-policy-directive = feature-identifier RWS allow-list
feature-identifier = 1*( ALPHA / DIGIT / "-")
allow-list = allow-list-value *(RWS allow-list-value)
allow-list-value = permissions-source-expression / "*" / "'self'" / "'src'" / "'none'"
permissions-source-expression = scheme-source / host-source
字符串 "'self'" 可作为 允许名单中的一个来源使用。当以此方式使用时,其表示包含 originDocument权限策略的来源。

5.2. 结构化头部序列化

策略指令在 HTTP 头中以结构化字段表示。[RFC8941]

在该表示中,策略指令以字典结构表示。

每个字典成员将一个特性与一个允许名单关联。成员名称必须是 Token。如果该 token 不是用户代理的已支持特性,则该字典成员会在处理步骤中被忽略。

成员值代表允许名单,必须为以下之一:

  • 包含 ASCII 权限来源表达式的字符串

  • Token *

  • Token self

  • 包含零个或多个上述项的内部列表(Inner List)。

成员值可以有名为 "report-to" 的参数,其值必须为字符串。其他参数将被忽略。

内部列表中的其他项会在处理步骤中被忽略,成员值将按未包含这些项的方式处理。其他形式的成员值会导致整个字典成员在处理步骤中被忽略。

6. 传递

6.1. `Permissions-Policy` HTTP 头字段

`Permissions-Policy` HTTP 头字段可用于响应(从服务器到客户端)以告知客户端应强制执行的权限策略

`Permissions-Policy` 是结构化头部,其值必须为字典。其 ABNF 为:

PermissionsPolicy = sf-dictionary

该字典的语义定义见 第5.2节 结构化头部序列化

处理步骤定义见 第9.2节 从字典和来源构建策略

6.2. iframe 元素的 allow 属性

iframe 元素有一个 allow 属性,内容为 ASCII 序列化策略指令

属性中指定特性的允许名单可以为空;此时允许名单的默认值为 'src',表示 iframe 的 src 属性 URL 的来源。

若属性不为空, allow 属性会为每个识别出的特性iframe 元素的内容可导航对象容器策略添加允许名单。

6.3. 支持旧特性的附加属性

部分由权限策略控制的特性已有 iframe 属性定义。本文规范将这些属性重新定义为影响 iframe内容可导航对象容器策略

6.3.1. allowfullscreen

allowfullscreen iframe 属性控制对 requestFullscreen() 的访问。

如果 iframe 元素有一个 allow 属性且值包含 "fullscreen",则 allowfullscreen 属性必须无效。

否则,iframe 元素存在 allowfullscreen 属性时,会为 "fullscreen" 特性在 iframe 元素的 内容可导航对象容器策略添加 允许名单 *

这与 <iframe allow="fullscreen"> 的行为不同,是为了兼容现有 allowfullscreen 用法。如果 allow="fullscreen"allowfullscreen 同时出现在 iframe 元素上,则会采用更严格的 allow="fullscreen" 的允许名单。

7. 脚本中的策略自省

7.1. 概述

文档中当前生效的策略可以被脚本观察。这可以用于决策,例如在无法确定某项特性是否启用的情况下决定展示什么用户界面。(有些特性可能没有可观察的失败模式,或者特性检测有副作用。)

文档和 iframe 都提供一个 PermissionsPolicy 对象,可用于检查适用于它们的权限策略。

7.1.1. 文档策略

要获取当前生效的策略,请使用 document.permissionsPolicy。它返回一个 PermissionsPolicy 对象,可用于:

  • 查询当前文档中指定特性的状态(允许或拒绝),

  • 获取当前文档中所有可用特性(无论是否允许)的列表,

  • 获取当前文档中所有允许特性的列表,或

  • 获取当前文档中指定特性的允许名单。

<!doctype html>
<script>
 const policy = document.permissionsPolicy;

 // 如果当前文档可以使用 WebUSB,则为 true。
 const can_use_usb = policy.allowsFeature('usb');

 // 如果 https://example.com 的新 frame 被允许使用 WebXR,则为 true。
 if (policy.allowsFeature('xr-spatial-tracking', 'https://example.com')) {
   // 显示用于创建 frame 的 UI。
 } else {
   // 显示其他 UI。
 }

 // 获取被允许请求支付的所有来源列表。结果为显式来源列表,或单一元素 ['*'],表示允许所有来源。
 const allowed_payment_origins = policy.getAllowlistForFeature('payment');

 // 获取当前文档支持的所有特性(即使未被允许)。结果为字符串数组,每个代表一个特性。
 const all_features = policy.features();
 if (all_features.includes('geolocation')) {
   // 添加一个子 frame 到第三方地图服务。
 }
</script>

7.1.2. 框架策略

也可以从包含 iframe 的文档中检查 iframe 元素上的策略。此时的策略对象代表该框架的可观察策略,仅依赖于当前文档和 iframe 元素的属性。它不会透露特性在该框架中当前是否被允许,因为框架中的文档可能已通过 HTTP 头应用了自己的策略,或已导航到新的来源。此时如果透露 iframe 元素嵌套导航中的实际策略,可能会泄露跨域文档的行为信息。

<!doctype html>
<iframe id="frame" allow="fullscreen; xr-spatial-tracking"></iframe>
<script>
 const iframe_element = document.getElementById("frame");
 const iframe_policy = iframe_element.permissionsPolicy;

 // 如果被嵌入的文档允许使用 WebXR,则为 true
 if (iframe_policy.allowsFeature('xr-spatial-tracking')) {
  // 显示虚拟现实控制
 }
</script>

iframe 元素上的可观察策略与实际加载到框架中的内容无关(避免跨域信息泄露),甚至与是否在文档树中也无关。

<!doctype html>
<!-- 当 src 属性中的文档被加载时,该 frame 不允许使用 fullscreen -->
<iframe id="frame" allow="fullscreen https://example.com" src="https://example.net/" ></iframe>
<script>
 const iframe_element = document.getElementById("frame");
 const iframe_policy = iframe_element.permissionsPolicy;
 // 由于 src 属性中的 URL 未被策略允许使用 fullscreen,这里为 false。
 const is_fullscreen_allowed_in_frame = iframe_policy.allowsFeature('fullscreen');

 const new_frame = document.createElement('iframe');
 new_frame.allow = 'sync-xhr';
 // 这里为 true,因为 iframe 被允许在其 src 属性指定的任何 URL 上使用 sync-xhr,即使该属性尚未设置。
 const is_sync_xhr_allowed = new_frame.permissionsPolicy.allowsFeature('sync-xhr');
</script>

7.2. permissionsPolicy 对象

[Exposed=Window]
interface PermissionsPolicy {
  boolean allowsFeature(DOMString feature, optional DOMString origin);
  sequence<DOMString> features();
  sequence<DOMString> allowedFeatures();
  sequence<DOMString> getAllowlistForFeature(DOMString feature);
};

partial interface Document {
    [SameObject] readonly attribute PermissionsPolicy permissionsPolicy;
};

partial interface HTMLIFrameElement {
    [SameObject] readonly attribute PermissionsPolicy permissionsPolicy;
};

PermissionsPolicy 对象有一个关联节点, 即一个 Node关联节点在创建 PermissionsPolicy 对象时设置。

PermissionsPolicy 对象有一个默认来源, 是一个来源,其值取决于 PermissionsPolicy 对象的关联节点状态:

每个 Document 都有一个策略对象, 是一个 PermissionsPolicy 实例,其 关联节点即该 Document

获取 DocumentpermissionsPolicy IDL 属性时,必须返回该 Document策略对象

每个 iframe 元素有一个策略对象, 是一个 PermissionsPolicy 实例,其 关联节点为 该元素本身。

获取 iframepermissionsPolicy IDL 属性时,必须返回该 iframe策略对象

allowsFeature(feature, origin) 方法必须执行以下步骤:

  1. 如果 origin 被省略,则将 origin 设为该 PermissionsPolicy 对象的 默认来源

  2. policy 为该对象的可观察策略

  3. 如果 policy 允许 featureorigin,返回 true。

  4. 否则返回 false。

features() 方法必须执行以下步骤:

  1. result 为一个空有序集合。

  2. 对每个已支持特性 feature

    1. feature 添加到 result

  3. 返回 result

allowedFeatures() 方法必须执行以下步骤:

  1. result 为一个空有序集合。

  2. origin 为该对象的 默认来源

  3. policy 为该对象的可观察策略

  4. 对每个已支持特性 feature

    1. 如果 policy 允许 featureorigin,则将 feature 添加到 result

  5. 返回 result

getAllowlistForFeature(feature) 方法必须执行以下步骤:

  1. result 为一个空列表。

  2. origin 为该对象的 默认来源

  3. policy 为该对象的可观察策略

  4. 如果 feature 未被 policy 允许对 origin,返回 result

  5. allowlistpolicy声明策略[feature] 的 声明

  6. 如果 allowlist 是特殊值 *

    1. 将 "*" 添加到 result

    2. 返回 result

  7. 如果 allowlistself-origin 不为 null, 则将其序列化添加到 result

  8. 如果 allowlistsrc-origin 不为 null, 则将其序列化添加到 result

  9. 否则,对 allowlist表达式中的每个权限来源表达式 item

    1. item 添加到 result

  10. 返回 result

任何 Node 的可观察策略是一个权限策略,包含从当前文档可见的可导航对象策略信息。

获取 Document document可观察策略,返回 document 的权限策略。

获取 Element node可观察策略,执行以下步骤:

  1. inherited policy 为一个空有序映射

  2. 对每个 已支持特性 feature

    1. isInherited 为运行 在容器中为来源定义特性的继承策略方法,参数为 featurenodenode声明来源

    2. 设置 inherited policy[feature] 为 isInherited

  3. 返回一个新的权限策略,其继承策略inherited policy声明策略为一个具有空 声明报告配置的新有序映射的结构体。

获取 Element node声明来源,执行以下步骤:

  1. 如果 node节点文档沙箱来源浏览上下文标志已设置,则返回一个新的不透明来源

  2. 如果 nodesandbox 属性已设置,且不包含 allow-same-origin 关键字,则返回一个新的不透明来源

  3. 如果 nodesrcdoc 属性已设置,则返回 node节点文档的来源。

  4. 如果 nodesrc 属性已设置:

    1. url 为解析 node 的 src 属性(相对于 node节点文档)的结果。

    2. 如果 url 不是失败,则返回 url 的来源。

  5. 返回 node节点文档的来源。

声明来源概念旨在表示嵌入页面意图加载到框架中的文档来源。这意味着,例如,如果浏览器不支持 sandboxsrcdoc 属性,则在计算声明来源时不应考虑这些属性。

8. 报告

权限策略违规报告表示某些Document的行为违反了权限策略。每个具体策略控制特性的规范需定义什么情况属于违反该策略,以及如何判断违规发生。

权限策略违规报告报告类型为 "permissions-policy-violation"。

权限策略违规报告ReportingObserver是可见的。

[Exposed=Window]
interface PermissionsPolicyViolationReportBody : ReportBody {
  [Default] object toJSON();
  readonly attribute DOMString featureId;
  readonly attribute DOMString? sourceFile;
  readonly attribute long? lineNumber;
  readonly attribute long? columnNumber;
  readonly attribute DOMString disposition;
  readonly attribute DOMString? allowAttribute;
  readonly attribute DOMString? srcAttribute;
};

权限策略违规报告body,在 JavaScript 中由 PermissionsPolicyViolationReportBody 表示,包含如下字段:

8.1. `Permissions-Policy-Report-Only` HTTP 头字段

`Permissions-Policy-Report-Only` HTTP 头字段可用于响应(服务器到客户端),以告知客户端不强制执行的权限策略,而是用于在其中声明的策略如果将要被违反时触发报告(假如该策略处于激活状态)。

`Permissions-Policy-Report-Only` 是结构化头部,其值必须为字典。

该字典的语义定义见 第5.2节 结构化头部序列化

处理步骤定义见 第9.2节 从字典和来源构建策略

9. 算法

9.1. 处理响应策略

给定一个responseresponse)、一个originorigin)和一个布尔值(report-only),本算法返回一个声明策略
  1. header name 为 "Permissions-Policy-Report-Only"(如果 report-only 为 True),否则为 "Permissions-Policy"。

  2. parsed header 为执行 获取结构化字段值,参数为 header name 和 "dictionary",从 responseheader list

  3. 如果 parsed header 为 null,返回一个空有序映射

  4. policy 为执行 从字典和来源构建策略(参数为 parsed headerorigin)的结果。

  5. 返回 policy

9.2. 从字典和来源构建策略

给定一个有序映射dictionary)和一个originorigin),本算法将返回一个声明策略
  1. declarations 为一个空有序映射

  2. reporting-config 为一个空有序映射

  3. 对于每个 feature-name → (value, params) 属于 dictionary

    1. 如果 feature-name 未识别为任何策略控制的特性,则继续

    2. feature 为由 feature-name 标识的策略控制的特性

    3. 如果 params["report-to"] 存在且为字符串,则令 reporting-config[feature] = params["report-to"]。

    4. allowlist 为一个新的允许名单

    5. 如果 value 是 token *,或 value 是包含 token * 的列表,则令 allowlist特殊值 *

    6. 否则:

      1. 如果 value 是 token self,令 allowlistself-originorigin

      2. 否则若 value列表,则对每个element属于value

        1. 如果 element 是 token self,令 allowlistself-originorigin

        2. 如果 element 是有效的权限来源表达式追加 elementallowlist表达式集合。

    7. declarations[feature] = allowlist

  4. 返回 «declarations, reporting-config»。

9.3. 解析策略指令

给定一个字符串(value)、一个origincontainer origin),以及一个可选的origintarget origin),本算法返回一个策略指令
  1. directive 为一个空有序映射

  2. 对于每个 serialized-declaration,由严格按分隔符U+003B(;)分割 value得到:

    1. tokens按 ASCII 空白分割 serialized-declaration的结果。

    2. 如果 tokens 是空列表,则继续

    3. feature-nametokens 的第一个元素。

    4. 如果 feature-name 未识别为任何策略控制的特性,则继续

    5. feature 为由 feature-name 标识的策略控制的特性

    6. targetlisttokens 的剩余元素(如有)。

    7. allowlist 为一个新的允许名单

    8. 如果 targetlist 中有任何元素为字符串 "*",则令 allowlist特殊值 *

    9. 否则:

      1. 如果 targetlist 为空且有 target origin,令 allowlistsrc-origintarget origin

      2. 对每个 element 属于 targetlist

        1. 如果 element 与 "'self'" ASCII 不区分大小写匹配:

          1. allowlistself-origincontainer origin

          2. 继续下一个 element

        2. 如果有 target originelement 与 "'src'" ASCII 不区分大小写匹配:

          1. allowlistsrc-origintarget origin

          2. 继续下一个 element

        3. result 为执行URL 解析器处理 element 的结果。

        4. 如果 result 不是失败:

          1. targetresult来源

          2. 如果 target 不是不透明来源追加 序列化后的 targetallowlist表达式集合。

    10. directive[feature] = allowlist

  3. 返回 directive

9.4. 处理权限策略属性

给定一个元素(element),本算法返回一个容器策略,可能为空。
  1. 如果 element 不是 iframe 元素,则返回一个空的策略指令

  2. container policy 为运行 解析策略指令,参数为 elementallow 属性值, element来源, 以及 element节点文档element声明来源

  3. 如果 elementallowfullscreen 属性被指定,且 container policy包含 fullscreen 特性的条目。

    1. 设置 container policy[fullscreen] = 特殊值 *

  4. 返回 container policy

9.5. 为可导航对象创建权限策略

给定 null 或一个元素container),以及一个来源origin),本算法返回一个新的权限策略
  1. 断言:如果不为 null,container 是一个可导航容器

  2. inherited policy 为一个新的有序映射

  3. 对每个 feature 已支持特性,

    1. isInherited 为运行 在容器中为来源定义特性的继承策略, 参数为 featurecontainerorigin 的结果。

    2. 设置 inherited policy[feature] = isInherited

  4. policy 为一个新的权限策略,其继承策略inherited policy声明策略为 «[], []»。

  5. 返回 policy

9.6. 根据响应为可导航对象创建权限策略

给定 null 或可导航容器container)、一个来源origin)、一个响应response),以及一个可选布尔值 (report-only,默认值为 False),本算法返回一个新的权限策略
  1. policy 为运行 为可导航对象创建权限策略 的结果,参数为 containerorigin

  2. d 为运行 处理响应策略 ,参数为 responseoriginreport-only 的结果。

  3. 对每个 featureallowlist 属于 d声明

    1. 如果 policy继承策略[feature] 为 true, 则设置 policy声明策略声明[feature] = allowlist

  4. 设置 policy声明策略[feature]的 报告配置d报告配置

  5. 返回 policy

9.7. 在容器中为来源定义特性的继承策略

给定一个特性feature)、null 或可导航容器container)、可导航对象中的Document来源origin),以及一个可选布尔值(report-only,默认值为 False),本算法返回 feature继承策略值
  1. 如果 container 为 null,返回 "Enabled"。

  2. 如果运行 获取指定来源的特性值,参数为 featurecontainer节点文档container节点文档的来源和 report-only 的结果为 "Disabled",返回 "Disabled"。

  3. 如果运行 获取指定来源的特性值,参数为 featurecontainer节点文档originreport-only 的结果为 "Disabled",返回 "Disabled"。

  4. container policy 为运行 处理权限策略属性 的结果,参数为 container

  5. 如果 feature 存在container policy

    1. 如果 container policyfeature允许名单 匹配 origin,返回 "Enabled"。

    2. 否则返回 "Disabled"。

  6. 如果 feature默认允许名单*,返回 "Enabled"。

  7. 如果 feature默认允许名单'self',且 origincontainer节点文档来源同源,返回 "Enabled"。

  8. 否则返回 "Disabled"。

9.8. 获取指定来源的特性值

给定一个特性feature)、一个Document 对象(document)、一个来源origin)、一个布尔值(report-only), 本算法如果该特性应被视为禁用则返回 "Disabled",否则返回 "Enabled"。
  1. policydocument仅报告权限策略(若 report-only 为 True),否则为 document权限策略

  2. 如果 policy继承策略feature 为 "Disabled", 返回 "Disabled"。

  3. 如果 feature 存在于 policy声明策略

    1. 如果 policy声明策略声明[feature] 匹配 origin, 返回 "Enabled"。

    2. 否则返回 "Disabled"。

  4. 返回 "Enabled"。

9.9. 检查权限策略

检查权限策略,给定权限策略policy)、特性feature)、来源origin)以及另一个来源document origin),如果应视该特性为禁用则返回 "Disabled",否则返回 "Enabled"。
  1. 如果 policy继承策略feature 为 "Disabled", 返回 "Disabled"。

  2. 如果 feature 存在于 policy声明策略

    1. 如果 policy声明策略声明[feature] 匹配 origin, 返回 "Enabled"。

    2. 否则返回 "Disabled"。

  3. 如果 feature默认允许名单*,返回 "Enabled"。

  4. 如果 feature默认允许名单'self',且 origindocument origin同源,返回 "Enabled"。

  5. 返回 "Disabled"。

9.10. 文档中指定来源的特性是否启用?

给定一个特性feature)、一个Document 对象(document)、一个来源origin)、一个可选布尔值(report,默认值为 True),如果该特性应被视为禁用则返回 "Disabled",否则返回 "Enabled"。若 report 为 True,则当特性在 document权限策略仅报告权限策略中未启用时,会生成并队列报告

注意: report 默认值 True 意味着多数权限策略检查在特性未启用时会生成违规报告。这是预期结果,因为大多数检查都是对实际特性使用进行的。如果只是查询特性状态而非实际尝试使用,应将 report 设为 False。

  1. policydocument权限策略

  2. report-only policydocument仅报告权限策略

  3. result 为调用检查权限策略,参数为 policyfeatureorigindocument来源

  4. report-only result 为调用检查权限策略,参数为 report-only policyfeatureorigindocument来源

  5. 如果 report 为 True:

    1. settingsdocument环境设置对象

    2. 如果 result 为 "Disabled":

      1. endpoint 为调用获取特性的报告端点,参数为 featurepolicy 的结果。

      2. 调用 为 settings 生成权限策略违规报告,参数为 featuresettings、"Enforce" 和 endpoint

    3. 否则,如果 report-only result 为 "Disabled":

      1. report-only endpoint 为调用获取特性的报告端点,参数为 featurereport-only policy 的结果。

      2. 调用 为 settings 生成权限策略违规报告,参数为 featuresettings、"Report" 和 report-only endpoint

  6. 返回 result

9.11. 获取特性的报告端点

给定一个特性feature)和一个权限策略policy), 本算法返回一个字符串,表示发送违规报告的端点名称,如果 policy 未声明端点,则返回 null。
  1. configpolicy声明策略报告配置

  2. 如果 config[feature] 存在,返回 config[feature]。

  3. 返回 null。

9.12. 检查容器中的权限策略潜在违规

给定一个可导航容器container)、一个字符串或 null (allowAttribute),一个字符串或 null (srcAttribute),本算法发送潜在违规报告。
  1. documentcontainer节点文档

  2. settingsdocument环境设置对象

  3. 对每个 已支持特性 feature

    1. 如果运行 在容器中为来源定义特性的继承策略, 参数为 featurecontainercontainer声明来源 的结果为 "Disabled":

      1. endpoint 为调用 获取特性的报告端点,参数为 featuredocument权限策略

      2. 调用 为 settings 生成潜在权限策略违规报告, 参数为 featuresettings、"Enforce"、endpointallowAttributesrcAttribute

    2. 否则,如果运行 在容器中为来源定义特性的继承策略, 参数为 featurecontainercontainer声明来源和 True 的结果为 "Disabled":

      1. report-only endpoint 为调用 获取特性的报告端点,参数为 featuredocument仅报告权限策略

      2. 调用 为 settings 生成潜在权限策略违规报告, 参数为 featuresettings、"Report"、report-only endpointallowAttributesrcAttribute

9.13. 为 settings 生成权限策略违规报告

给定一个特性feature)、一个环境设置对象 (settings)、一个字符串(disposition)、一个字符串或 null(endpoint), 本算法生成一个关于 feature 策略违规的报告
  1. body 为一个新的 PermissionsPolicyViolationReportBody, 初始化如下:

    featureId

    feature 的字符串表示。

    sourceFile

    null

    lineNumber

    null

    columnNumber

    null

    disposition

    disposition

  2. 如果用户代理当前正在执行脚本,且能从 settings 提取源文件 URL、行号和列号,则相应设置 bodysourceFilelineNumbercolumnNumber

  3. 执行 生成并队列报告,参数为 body、 "permissions-policy-violation"、endpointsettings

9.14. 为 settings 生成潜在权限策略违规报告

给定一个特性feature)、一个环境设置对象 (settings)、一个字符串(disposition)、一个字符串或 null(endpoint)、一个字符串或 null(allowAttribute)、一个字符串或 null(srcAttribute), 本算法生成一个关于 feature 策略潜在违规的报告
  1. body 为一个新的 PermissionsPolicyViolationReportBody, 初始化如下:

    featureId

    feature 的字符串表示。

    sourceFile

    null

    lineNumber

    null

    columnNumber

    null

    disposition

    disposition

    allowAttribute

    allowAttribute

    srcAttribute

    srcAttribute

  2. 如果用户代理当前正在执行脚本,且能从 settings 提取源文件 URL、行号和列号,则相应设置 bodysourceFilelineNumbercolumnNumber

  3. 执行 生成并队列报告,参数为 body、 "potential-permissions-policy-violation"、endpointsettings

9.15. 请求是否允许使用特性?

给定一个特性feature)和一个请求request), 本算法如果请求应被允许使用 feature 则返回 true,否则返回 false
  1. clientrequestclient

  2. 如果 client 为 null,返回 false

  3. 如果 client全局对象不是 Window, 返回 false

    非 Window 上下文( WorkerGlobalScopeWorkletGlobalScope 的权限策略正在 issue #207 中讨论。待定后,更新本算法以允许这些上下文中的 fetch 使用策略控制的特性。 在此之前,这些上下文中所有策略控制的特性(如向第三方发送 Client Hints)均不允许。
  4. 设置 documentclient全局对象关联 Document

  5. originrequest来源

  6. result 为运行 文档中指定来源的特性是否启用?, 参数为 featuredocumentorigin

  7. 如果 result 为 "Enabled",返回 true

  8. 否则返回 false

10. 对其他规范的变更

10.1. 对 HTML 规范的变更

每个 Document 都有一个仅报告权限策略, 即一个权限策略,初始为空。

7.5.1 共享文档创建基础设施,第3步后插入如下步骤:

  1. reportOnlyPermissionsPolicy 为调用 根据响应为可导航对象创建权限策略, 参数为 navigationParams 的 navigable 的 container、navigationParams 的 origin、navigationParams 的 response 和 True 的结果。

并在同一节第10步,设置新 Document仅报告权限策略reportOnlyPermissionsPolicy

iframe 加载事件步骤,第6步后插入如下步骤:

  1. 调用 检查容器中的权限策略潜在违规, 参数为 elementelement 的 allow 属性、element 的 src 属性。

11. IANA 注意事项

应更新永久消息头字段注册表,内容如下 [RFC3864]

头字段名称
Permissions-Policy
适用协议
http
状态
standard
作者/变更控制方
W3C
规范文档
https://www.w3.org/TR/permissions-policy/

12. 隐私与安全

本规范标准化了一种机制,允许嵌入页面为被嵌入页面设置并强制执行策略。类似于 iframe 的 sandbox ,无需被嵌入页面的明确许可即可实现,这意味着通过在另一个文档中以合适的容器策略嵌入,已发布网站的现有特性行为可能被改变。

因此,最大的隐私和安全关注点包括:

在一定程度上,这些问题在 Web 平台中已存在,本规范至少试图不使其变得更糟。

安全和隐私问题还可能由各特性设计导致,因此集成本规范时需谨慎。本节尝试对哪些行为可能引发此类问题提供指导。

12.1. 跨域行为暴露

特性设计应确保在框架文档中违反策略时,其他框架的文档无法观察到。例如,假设某特性在策略禁用时被使用,会在嵌入文档中触发事件,则嵌入者可借此获知嵌入文档的状态。如果该特性仅在用户登录时被使用,嵌入者可为该框架禁用该特性,再监听事件,以判断用户是否已登录。

自省 API 设计只显示嵌入文档可推断出的子框架策略信息。该可观察策略不受框架文档通过 HTTP 头传递的影响,也不会因框架自身导航(即便切换到不同来源、应用不同策略)而改变。只有通过设置 src 属性进行导航,<iframe> 元素的可观察策略才会更新。

12.2. 意外行为变更

权限策略机制赋予文档在子框架加载时控制哪些特性可用的能力。如果某特性代表 Web 平台的现有、长期行为,这可能意味着 Web 上已发布内容并未预期特定 API 会失败。

举个实际(但人为)的例子,假设有文档用同步 XMLHttpRequest 检查用户是否有足够权限访问页面:

<!DOCTYPE html>
<h1>欢迎来到 SecureCorp!</h1>
<script>
  var req = new XMLHttpRequest();
  req.open("GET", "/api/security_check.json", false);
  req.send();
  if (req.response == "untrusted user") {
    // 用户未登录,重定向到安全页面
    location.href = "/security_check_failed.html";
  }
</script>
<!-- 页面继续,假设用户已登录 -->

如果该文档被页面嵌入且禁用了 "sync-xhr" 特性,则 XMLHttpRequest.open() 调用会失败,安全检查就会被绕过。

注意,此类强制行为在 Web 上原本就可能发生:有些特性只允许在顶级文档使用,在任何 iframe 都不允许,iframe 沙箱也可用类似方式嵌入不具备某些依赖特性的框架。

一般来说,此问题有两种缓解方式:

集成特性到权限策略时,作者可决定文档在特性被禁用时何时及如何失败。应尽量利用已有失败模式,以提高现有内容已正确处理此类失败的概率。

12.3. 嵌入策略暴露

已采取措施限制页面能推断的跨域嵌入页面行为信息。但在某些场景下,被嵌入页面可通过检查嵌入者强制的策略推断嵌入者信息。

这类似于现有的 document.fullscreenEnabled 属性,嵌入文档可由此推断嵌入者是否赋予其使用全屏 API 的能力。如果只有在特定情形(如用户登录嵌入站点时)才赋予权限,则被嵌入站点可获知嵌入者的状态。

13. 变更日志

13.1. 自 FPWD 的变更

一致性

文档约定

一致性要求通过描述性断言与 RFC 2119 术语结合表达。 规范性部分中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY” 和 “OPTIONAL” 按照 RFC 2119 的定义进行解释。 为提高可读性,本规范未将这些词全部大写书写。

除非明确标注为非规范性、示例和注释,否则本规范所有文本均为规范性内容。[RFC2119]

本规范中的示例以“例如”引入,或使用 class="example" 与规范性文本区分,如下所示:

这是一个说明性示例。

说明性注释以“注意”开头,并用 class="note" 与规范性文本区分,如下所示:

注意,这是一个说明性注释。

一致性算法

在算法部分以祈使语气表达的要求(如“去除所有前导空格字符”或“返回 false 并终止这些步骤”) 应结合引入该算法时所用关键词(如 “must”、“should”、“may” 等)来理解其含义。

以算法或具体步骤表达的一致性要求可用任何方式实现,只要最终结果等效即可。 本规范中的算法主要为易于理解而设计,并非以高性能为目标。鼓励实现者进行优化。

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[CSP3]
Mike West; Antonio Sartori. 内容安全策略第3级。2025年7月11日。WD。URL:https://www.w3.org/TR/CSP3/
[DOM]
Anne van Kesteren. DOM标准。现行标准。URL:https://dom.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch标准。现行标准。URL:https://fetch.spec.whatwg.org/
[FULLSCREEN]
Philip Jägenstedt. 全屏API标准。现行标准。URL:https://fullscreen.spec.whatwg.org/
[HTML]
Anne van Kesteren; 等。HTML标准。现行标准。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra标准。现行标准。URL:https://infra.spec.whatwg.org/
[REPORTING-1]
Douglas Creager; Ian Clelland; Mike West. 报告API。2025年6月11日。WD。URL:https://www.w3.org/TR/reporting-1/
[RFC2119]
S. Bradner. 用于指示需求级别的RFC关键字。1997年3月。最佳当前实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[RFC3864]
G. Klyne; M. Nottingham; J. Mogul. 消息头字段注册过程。2004年9月。最佳当前实践。URL:https://www.rfc-editor.org/rfc/rfc3864
[RFC8941]
M. Nottingham; P-H. Kamp. HTTP结构化字段值。2021年2月。拟定标准。URL:https://httpwg.org/specs/rfc8941.html
[URL]
Anne van Kesteren. URL标准。现行标准。URL:https://url.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL标准。现行标准。URL:https://webidl.spec.whatwg.org/

参考性引用

[CSP2]
Mike West; Adam Barth; Daniel Veditz. 内容安全策略第2级。2016年12月15日。REC。URL:https://www.w3.org/TR/CSP2/
[HTML5]
Ian Hickson; 等。HTML5。2018年3月27日。REC。URL: https://www.w3.org/TR/html5/
[MEDIACAPTURE-STREAMS]
Cullen Jennings; 等。媒体采集与流。2025年9月25日。CRD。URL:https://www.w3.org/TR/mediacapture-streams/
[PERMISSIONS]
Marcos Caceres; Mike Taylor. 权限。2025年9月26日。WD。URL:https://www.w3.org/TR/permissions/

IDL 索引

[Exposed=Window]
interface PermissionsPolicy {
  boolean allowsFeature(DOMString feature, optional DOMString origin);
  sequence<DOMString> features();
  sequence<DOMString> allowedFeatures();
  sequence<DOMString> getAllowlistForFeature(DOMString feature);
};

partial interface Document {
    [SameObject] readonly attribute PermissionsPolicy permissionsPolicy;
};

partial interface HTMLIFrameElement {
    [SameObject] readonly attribute PermissionsPolicy permissionsPolicy;
};

[Exposed=Window]
interface PermissionsPolicyViolationReportBody : ReportBody {
  [Default] object toJSON();
  readonly attribute DOMString featureId;
  readonly attribute DOMString? sourceFile;
  readonly attribute long? lineNumber;
  readonly attribute long? columnNumber;
  readonly attribute DOMString disposition;
  readonly attribute DOMString? allowAttribute;
  readonly attribute DOMString? srcAttribute;
};

问题索引

本规范目前仅涉及文档中定义的特性。我们应考虑如何表述,以包含 Worker 和 Worklet 中的特性与权限策略。
非 Window 上下文中的权限策略( WorkerGlobalScopeWorkletGlobalScope )正在 issue #207 讨论。待定后,更新本算法以允许这些上下文中的 fetch 使用策略控制的特性。 在此之前,这些上下文中所有策略控制的特性(如向第三方发送 Client Hints)均不允许。
MDN

Headers/Feature-Policy

仅在一个主流引擎实现。

Firefox无支持Safari无支持Chrome60+
Opera?Edge79+
Edge (旧版)?IE无支持
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

Headers/Permissions-Policy

仅在一个主流引擎实现。

Firefox无支持Safari无支持Chrome88+
Opera?Edge88+
Edge (旧版)?IE无支持
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?