-
Notifications
You must be signed in to change notification settings - Fork 36
Add permissions patches #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1dbc531
e6fab75
0be10c0
238f436
3f18b19
60f812f
29ecb23
6ef8d10
7c8a3ba
5b6b0f5
b78ea8b
33fd180
8706212
e24bf6c
c6644e7
bbc1ca9
0b94042
919a0af
311455e
962de69
bf59afa
acf08d2
7d3bed4
d8115f4
b2a4b96
05e7ec4
642b67a
b47f023
cad5853
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,9 +80,11 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/ | |
| text: historyHandling; url: navigation-hh | ||
| text: referrerPolicy; url: navigation-referrer-policy | ||
| text: attempt to populate the history entry's document; url: attempt-to-populate-the-history-entry's-document | ||
| text: navigation params; url: navigation-params | ||
| for: navigation params | ||
| text: response; url: navigation-params-response | ||
| text: navigable; url: navigation-params-navigable | ||
| text: origin; url: navigation-params-origin | ||
| for: history handling behavior | ||
| text: replace; url: hh-replace | ||
| for: document state | ||
|
|
@@ -109,6 +111,21 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/ | |
| urlPrefix: nav-history-apis.html | ||
| for: Window | ||
| text: navigable; url: window-navigable | ||
| urlPrefix: webappapis.html | ||
| for: environment | ||
| text: target browsing context; url: concept-environment-target-browsing-context | ||
| urlPrefix: document-sequences.html | ||
| for: browsing context | ||
| text: active document; url: active-document | ||
| spec: fetch; urlPrefix: https://fetch.spec.whatwg.org/ | ||
| type: dfn | ||
| text: queue a cross-origin embedder policy CORP violation report; url: queue-a-cross-origin-embedder-policy-corp-violation-report | ||
| text: should request be blocked due to a bad port; url: block-bad-port | ||
| spec: mixed-content; urlPrefix: https://w3c.github.io/webappsec-mixed-content/ | ||
| type: dfn | ||
| text: should fetching request be blocked as mixed content; url: should-block-fetch | ||
| spec: CSP; urlPrefix: https://w3c.github.io/webappsec-csp/ | ||
| type: dfn | ||
| urlPrefix: interactive-elements.html | ||
| text: accesskey attribute command; url: using-the-accesskey-attribute-to-define-a-command-on-other-elements | ||
| text: previously focused element; url: previously-focused-element | ||
|
|
@@ -125,6 +142,16 @@ spec: RFC8941; urlPrefix: https://www.rfc-editor.org/rfc/rfc8941.html | |
| text: structured header; url: #section-1 | ||
| for: structured header | ||
| text: token; url: name-tokens | ||
| spec: permissions-policy; urlPrefix: https://w3c.github.io/webappsec-permissions-policy | ||
| type: dfn | ||
| text: ASCII-serialized policy directive; url: serialized-policy-directive | ||
| text: serialized permissions policy; url: serialized-permissions-policy | ||
| text: supported features; url: supported-features | ||
| text: declared policy; url: declared-policy | ||
| text: the special value *; url: the-special-value | ||
| text: permissions policy; url: permissions-policy | ||
| for: permissions | ||
| text: matches; url: matches | ||
| spec: CSP; urlPrefix: https://w3c.github.io/webappsec-csp/ | ||
| type: dfn | ||
| text: directive value; url: directive-value | ||
|
|
@@ -258,6 +285,7 @@ dl, dd { | |
| <dd>[=Global attributes=]</dd> | ||
| <dd><code>[=width=]</code> — Horizontal dimension</dd> | ||
| <dd><code>[=height=]</code> — Vertical dimension</dd> | ||
| <dd><code><{fencedframe/allow}></code> — [=Permissions policy=] to be applied to the <{fencedframe}>'s contents</dd> | ||
| <dt>[=Accessibility considerations=]:</dt> | ||
| <dd><p class=XXX>TODO</p></dd> | ||
| <dt>[=DOM interface=]:</dt> | ||
|
|
@@ -270,6 +298,7 @@ interface HTMLFencedFrameElement : HTMLElement { | |
| [CEReactions] attribute FencedFrameConfig? config; | ||
| [CEReactions] attribute DOMString width; | ||
| [CEReactions] attribute DOMString height; | ||
| [CEReactions] attribute DOMString allow; | ||
| }; | ||
| </xmp> | ||
| </dd> | ||
|
|
@@ -344,6 +373,14 @@ The <dfn attribute for=HTMLFencedFrameElement>config</dfn> IDL attribute getter | |
| 1. <span class=XXX>TODO</span> | ||
| </div> | ||
|
|
||
| The <dfn element-attr for=fencedframe>allow</dfn> attribute, when specified, determines the | ||
| [=container policy=] that will be used when the [=Document/permissions policy=] for a {{Document}} | ||
| in the <{fencedframe}>'s [=fenced navigable container/fenced navigable=] is initialized. Its value | ||
| must be a [=serialized permissions policy=]. [[!PERMISSIONS-POLICY]] | ||
|
|
||
| The IDL attribute <dfn attribute for=HTMLFencedFrameElement>allow</dfn> must [=reflect=] the | ||
| respective content attribute of the same name. | ||
|
|
||
| <h3 id=dimension-attributes>Dimension attributes</h3> | ||
|
|
||
| This section details monkeypatches to [[!HTML]]'s <a | ||
|
|
@@ -1024,8 +1061,6 @@ Note: This is because we need to ensure that we do not leak <var ignore>creator< | |
| document's referrer|referrer=], [=Document/origin=], [=creator base url=], [=Document/policy | ||
| container=], across the fenced frame boundary. | ||
|
|
||
| Issue: Ensure we are doing the right thing for [=Document/permissions policy=]. | ||
|
|
||
| <h3 id=nested-traversables>Nested traversables</h3> | ||
|
|
||
| <h4 id=nested-traversables-intro>Introduction</h4> | ||
|
|
@@ -1731,3 +1766,239 @@ specification is printed below: | |
| /fenced-frame/cspee.https.html | ||
| /fenced-frame/embedder-csp-not-propagate.https.html | ||
| </wpt> | ||
|
|
||
| <h3 id=permissions-policy-changes>Permissions Policies</h3> | ||
|
|
||
| *This introductory sub-section is non-normative.* | ||
|
|
||
| The [=policy-controlled features=] available to {{Document}}s inside of a <{fencedframe}> are | ||
| determined exclusively by the {{FencedFrameConfig}} that the <{fencedframe}> navigates to. | ||
| Specifically, the {{FencedFrameConfig}}'s [=fencedframeconfig/config=]'s [=fenced frame | ||
| config/effective enabled permissions=] defines the exclusive list of [=policy-controlled features=] | ||
| that will be enabled in the {{Document}} (all others will be disabled). | ||
|
|
||
| During navigation, the {{FencedFrameConfig}}'s [=fencedframeconfig/config=] [=instantiate a | ||
| config|instantiates=] a [=navigable/fenced frame config instance=] that is stored on the [=fenced | ||
| navigable container/fenced navigable=]. This navigable's [=navigable/fenced frame config | ||
| instance=]'s [=fenced frame config instance/effective enabled permissions=] is consulted [=Should | ||
| navigation response to navigation request be blocked by Permissions Policy?|during navigation=]. A | ||
| <{fencedframe}> navigation can only succeed if the [=Document/permissions policy=] for the | ||
| navigation's resulting {{Document}} has an [=permissions policy/inherited policy=] such that the | ||
| [=inherited policy for a feature|inherited policy value=] is "`Enabled`" for each feature in the | ||
| [=fenced frame config/effective enabled permissions=]. Otherwise the environment the <{fencedframe}> | ||
| is embedded in is deemed unsuitable for the [=fenced frame config=], and the navigation is blocked. | ||
|
|
||
| At the same time, to make sure that a <{fencedframe}>'s embedder does not directly influence content | ||
| in the frame based on that navigation's [=navigation params/origin=] (since the origin is derived | ||
| from cross-site data), this specification modifies various [[PERMISSIONS-POLICY]] algorithms such | ||
| that a <{fencedframe}> {{Document}}'s [=permissions policy/inherited policy=] is computed without | ||
| consideration of whether its [=navigation params/origin=] is [=same origin=] with its embedder's. | ||
| Therefore a feature can only be enabled inside of a <{fencedframe}> if its embedder *explicitly* | ||
| delegates it via [=the special value *=] [=allowlist=]. | ||
|
|
||
| Considering all of the above, we get the following interesting implications: | ||
|
|
||
| * If a [=policy-controlled feature|feature=] that [=list/exists=] in the [=fenced frame | ||
| config/effective enabled permissions=] has a [=policy-controlled feature/default allowlist=] of | ||
| [=the special value *=], and no \`<a http-header>`Permissions-Policy`</a>\` header is served on | ||
| the <{fencedframe}> embedder, and the <{fencedframe/allow}> attribute is empty, the navigation | ||
| inside the <{fencedframe}> will succeed, and the resulting {{Document}} will be [=allowed to | ||
| use=] the [=policy-controlled feature|feature=] (i.e., it will be enabled). | ||
|
|
||
| * If a [=policy-controlled feature|feature=] that [=list/exists=] in the [=fenced frame | ||
| config/effective enabled permissions=] has a [=policy-controlled feature/default allowlist=] of | ||
| <a for="default allowlist">`'self'`</a>, and no \`<a http-header>`Permissions-Policy`</a>\` | ||
| header is served on the <{fencedframe}> embedder, and the <{fencedframe/allow}> attribute is | ||
| empty, the navigation inside the <{fencedframe}> will be blocked. | ||
|
|
||
| Note: This is because ordinarily this [=policy-controlled feature|feature=] would only be enabled | ||
| if the subframe's {{Document}} was [=same origin=] with its embedder, a check this specification | ||
| avoids for fenced frames, since the <{fencedframe}>s {{Document}}'s [=Document/origin=] is | ||
| derived from cross-site data. Therefore, we simply "fail close". | ||
|
|
||
| * If a [=policy-controlled feature|feature=] that [=list/exists=] in the [=fenced frame | ||
| config/effective enabled permissions=] has a [=policy-controlled feature/default allowlist=] of | ||
| <a for="default allowlist">`'self'`</a>, and the <{fencedframe}>'s <{fencedframe/allow}> | ||
| attribute contains the [=policy-controlled feature|feature=] but no [=allowlist=], the rules | ||
| described in <a href=allow-attribute-fenced-frame>The `allow` attribute section</a>, the default | ||
| [=allowlist=] for the feature will be `'src'` which is meant to represent the embedder-supplied | ||
| navigation [=URL=], for which there is none when navigating a <{fencedframe}>, as the navigation | ||
| [=URL=] is determined by the [=fenced frame config=]. The navigation will be blocked. | ||
|
|
||
| * If a [=policy-controlled feature|feature=] that [=list/exists=] in the [=fenced frame | ||
| config/effective enabled permissions=] has a [=policy-controlled feature/default allowlist=] of | ||
| <a for="default allowlist">`'self'`</a> but either the \`<a | ||
| http-header>`Permissions-Policy`</a>\` header served on the <{fencedframe}>'s embedder *OR* the | ||
| <{fencedframe/allow}> attribute sets that [=policy-controlled feature|feature=]'s [=allowlist=] | ||
| to [=the special value *=], then the navigation inside the <{fencedframe}> will succeed, and the | ||
| resulting {{Document}} is [=allowed to use=] the [=policy-controlled feature|feature=]. | ||
|
|
||
| * If a navigation inside a <{fencedframe}> would otherwise succeed, but the [=response=] on the | ||
| navigation inside the <{fencedframe}> is served with a \`<a | ||
| http-header>`Permissions-Policy`</a>\` header that sets the [=allowlist=] to "`none`" or an | ||
| otherwise incompatible [=origin=] for a feature in the [=fenced frame config/effective enabled | ||
| permissions=], the navigation still succeeds, but the {{Document}} in the <{fencedframe}> is | ||
| **not** [=allowed to use=] the feature. | ||
|
|
||
| Note: This is OK because it is the <{fencedframe}>'s content *itself* that is making the decision | ||
| to disable a particular feature, not its embedder environment. | ||
|
|
||
| The patches in the below section "fence" the appropriate [[PERMISSIONS-POLICY]] algorithms to | ||
| achieve the outcomes described in the above explanatory content. | ||
|
|
||
| <h4 id=permissions-policy-patches>Algorithm patches</h4> | ||
|
|
||
| <div id=allow-attribute-fenced-frame algorithm=allow-attribute-fenced-frame> | ||
| Rename the <a href=https://w3c.github.io/webappsec-permissions-policy/#iframe-allow-attribute>The | ||
| `allow` attribute of the `iframe` element</a> section to "The `allow` attribute of the `iframe` | ||
| and `fencedframe` element", and rewrite the section to read: | ||
|
|
||
| <{iframe}> and <{fencedframe}> elements have an respective `allow` attributes (<{iframe}>: | ||
| <{iframe/allow}>; <{fencedframe}>: <{fencedframe/allow}>), which contain an [=ASCII-serialized | ||
| policy directive=]. | ||
|
|
||
| The allowlist for the features named in the attribute may be empty; in that case, the default | ||
| value for the [=allowlist=] is "`src`", which represents the origin of the URL in the iframe's | ||
| <{iframe/src}> attribute, or the fencedframe's [=fenced frame config=]. | ||
|
|
||
| When not empty, the <{iframe}>'s <{iframe/allow}> or <{fencedframe}>'s <{fencedframe/allow}> | ||
| attribute will result in adding an [=allowlist=] for each [=supported feature=] to the <{iframe}> | ||
| or <{fencedframe}>'s [=container policy=]. | ||
| </div> | ||
|
|
||
| <div algorithm=create-permissions-policy> | ||
| Modify the [$Create a Permissions Policy for a navigable$] algorithm: | ||
|
|
||
| Given null or an element (|container|), an [=origin=] (|origin|), and an optional [=boolean=] | ||
| |fenced| that defaults to false, this algorithm returns a new Permissions Policy. | ||
|
|
||
| Rewrite step 1 to read: | ||
|
|
||
| 1. [=Assert=]: if not null, <var ignore>container</var> is either a [=navigable container=] or a | ||
| [=fenced navigable container=]. | ||
|
|
||
| Rewrite step 4 to read: | ||
|
|
||
| 4. For each |feature| supported: | ||
|
|
||
| 1. Let |isInherited| be the result of running [$Define an inherited policy for feature in | ||
| container at origin$] on |feature|, |container|, |origin|, and |fenced|. | ||
|
|
||
| 2. Set <var ignore>inherited policy</var>[|feature|] to |isInherited|. | ||
| </div> | ||
|
|
||
| <div algorithm=create-permissions-policy-response> | ||
| Modify the [$Create a Permissions Policy for a navigable from response$] algorithm to read: | ||
|
|
||
| Given null, a [=navigable container=], or a [=fenced navigable container=] (|container|), an | ||
| [=origin=] (|origin|), and a [=response=] (<var ignore>response</var>), this algorithm returns a | ||
| new [=Document/permissions policy=]. | ||
|
|
||
| Add a step before step 1 that reads: | ||
|
|
||
| 1. Let |fenced| be true if |container| is a [=fenced navigable container=], and false otherwise. | ||
|
|
||
| Modify what is *now* step 2 of the algorithm to read: | ||
|
|
||
| 2. Let <var ignore>policy</var> be the result of running [$Create a Permissions Policy | ||
| for a navigable$] given |container|, |origin|, and |fenced|. | ||
| </div> | ||
|
|
||
| <div algorithm=attempt-populate-history-patches> | ||
| Modify [[HTML]]'s [=attempt to populate the history entry's document=] algorithm. Add a step | ||
| before the step inside the [=queue a task|queued task=] starting with "If | ||
| |failure| is true, then:" that reads: | ||
|
|
||
| 8. Otherwise, if the result of [=Should navigation response to navigation request be blocked by | ||
| Permissions Policy?=] given <var ignore>navigationParams</var> is "`Blocked`", then set | ||
| |failure| to true. | ||
|
|
||
| Note: If this algorithm returns "`Blocked`", the pre-existing {{Document}} in the <{fencedframe}> | ||
| does not stick around; an error page will be loaded. | ||
| </div> | ||
|
|
||
| <div algorithm=permissions-policy-block-request> | ||
| Create a new algorithm called <dfn>Should navigation response to navigation request be blocked by | ||
| Permissions Policy?</dfn> in [[!HTML]]. | ||
blu25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Given a [=navigation params=] (|navigationParams|), this algorithm returns "`Blocked`" or | ||
| "`Allowed`": | ||
|
|
||
| 1. Let |navigable| be |navigationParams|'s [=navigation params/navigable=]. | ||
|
|
||
| 1. If |navigable| is not a [=fenced navigable container/fenced navigable=], then return | ||
| "`Allowed`". | ||
|
|
||
| 1. Let |origin| be |navigationParams|'s [=navigation params/origin=]. | ||
|
|
||
| 1. Let |effective permissions| be the |navigable|'s [=navigable/fenced frame config instance=]'s | ||
| [=fenced frame config instance/effective enabled permissions=]. | ||
|
|
||
| 1. Let |permissions policy| be the result of [$Create a Permissions Policy for a navigable| | ||
| creating a permissions policy$] given |navigable|'s [=fenced navigable container=], |origin|, | ||
| and <var ignore>fenced</var> set to true. | ||
|
|
||
| Note: This is identical to the [=Document/permissions policy=] that will be created when the | ||
| navigation constructs the ultimate {{Document}} for this pending navigation. We create it now | ||
| and run tests on it since this is the appropriate time to determine if a navigation will fail, | ||
| and then throw it away. If the navigation succeeds, it will be recreated identically and | ||
| unconditionally installed on the {{Document}}. | ||
|
|
||
| 1. Let |inherited policy| be |permissions policy|'s [=permissions policy/inherited policy=]. | ||
|
|
||
| 1. [=list/For each=] |effective permission| of |effective permissions|: | ||
|
|
||
| 1. If |inherited policy|[|effective permission|] is "Disabled", return "`Blocked`". | ||
|
|
||
| 1. Return "`Allowed`." | ||
| </div> | ||
|
|
||
| <div algorithm=define-inherited-policy-in-container-patches> | ||
| Modify the [$Define an inherited policy for feature in container at origin$] algorithm to | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to also modify this algorithm to "fence" the container policy look-up? Right now https://w3c.github.io/webappsec-permissions-policy/#define-inherited-policy-in-container looks at the container policy (which may contain 'none',
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Filed #82 so we can just land this PR now. |
||
| read: | ||
|
|
||
| Given a feature (|feature|), null or a [=navigable container=] (|container|), an [=origin=] for a | ||
| document in that container (|origin|), and an optional [=boolean=] |fenced| that defaults to | ||
| false, this algorithm returns the [=permissions policy/inherited policy=] for that feature. | ||
|
|
||
| Rewrite step 3 to read: | ||
|
|
||
| 3. If the result of executing [$Is feature enabled in document for origin?$] on |feature|, | ||
| |container|'s [=Node/node document=], |origin|, and |fenced| is "Disabled", return | ||
| "Disabled". | ||
|
|
||
| Note: We don't have to rewrite step 2, which also delegates to the same algorithm, to pass in the | ||
| |fenced| [=boolean=] because step 2 has to do with checking to see if |feature| is enabled | ||
| |container|'s [=Node/node document=], not the {{Document}} hosted *inside* |container|. | ||
|
|
||
| Rewrite step 7 to read: | ||
|
|
||
| 7. If |fenced| is false, |feature|'s [=policy-controlled feature/default allowlist=] is | ||
| `'self'`, and |origin| is [=same origin=] with |container|'s [=Node/node document=]'s | ||
| origin, return `"Enabled"`. | ||
| </div> | ||
|
|
||
| <div algorithm=is-feature-enabled-patches> | ||
| Modify the [$Is feature enabled in document for origin?$] algorithm to read: | ||
|
|
||
| Given a feature (|feature|), a {{Document}} object (|document|), an [=url/origin=] (|origin|), and | ||
| an optional [=boolean=] |fenced| that defaults to false, this algorithm returns "`Disabled`" if | ||
| |feature| should be considered disabled, and "`Enabled`" otherwise. | ||
|
|
||
| Rewrite step 3 to read: | ||
|
|
||
| 3. If |feature| is present in |policy|'s [=declared policy=], | ||
|
|
||
| 1. If |fenced| is set to false, and the [=allowlist=] for |feature| in |policy|'s [=declared | ||
| policy=] [=permissions/matches=] |origin|, then return "`Enabled`". | ||
|
|
||
| 2. Otherwise, if |fenced| is set to true, and the [=allowlist=] for |feature| in |policy|'s | ||
| [=declared policy=] is [=the special value *=], then return "`Enabled`". | ||
|
|
||
| 3. Otherwise, return "`Disabled`". | ||
|
|
||
| Rewrite step 5 to read: | ||
|
|
||
| 5. If |fenced| is set to false, |feature|'s [=policy-controlled feature/default allowlist=] is | ||
| `'self'`, and |origin| is [=same origin=] with |document|'s origin, return "Enabled". | ||
| </div> | ||
Uh oh!
There was an error while loading. Please reload this page.