Skip to content
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

Spec: Wait for network revocation in nested fenced frames before disabling network. #176

Merged
merged 39 commits into from
Jan 7, 2025
Merged
Changes from 35 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c9cbe3f
disableUntrustedNetwork skeleton
Apr 3, 2024
39d31fb
fill out more
Apr 9, 2024
7eaf2b1
more
Apr 9, 2024
c4705a6
address comments
Apr 11, 2024
ab9785d
skeleton
Jul 10, 2024
d75f324
content done % links
Jul 17, 2024
294e5fd
Merge remote-tracking branch 'origin/revoke-network' into liam-nested…
blu25 Aug 6, 2024
7c89c4e
Update spec.bs
blu25 Aug 8, 2024
0ce475f
remove 'defaults to'
blu25 Sep 11, 2024
2fc1484
Merge branch 'master' into liam-nested-revocation
blu25 Sep 11, 2024
c92fa38
address comments for code that's new in this PR
blu25 Sep 11, 2024
d94859f
Update spec.bs
blu25 Sep 12, 2024
9b6e158
attempt to fix validation errors
blu25 Sep 12, 2024
5d982b3
attempt to fix validation errors
blu25 Sep 12, 2024
f760c12
Merge branch 'master' into liam-nested-revocation
blu25 Sep 12, 2024
44435e0
test if removing the note fixes the build
blu25 Sep 12, 2024
78d1673
attempt to fix validation errors
blu25 Sep 12, 2024
77e3bd4
Update spec.bs
blu25 Sep 12, 2024
f5b1255
remove "can disable untrusted network"
blu25 Sep 12, 2024
a51ffdd
convert same-origin check to assert
blu25 Sep 12, 2024
5316240
update credentialless issue link
blu25 Sep 12, 2024
a24cd13
Merge branch 'master' into revoke-network
blu25 Sep 12, 2024
62f3b43
add changes from other review
blu25 Sep 12, 2024
49fe6a2
address comments
blu25 Sep 12, 2024
eb6bae4
Merge branch 'revoke-network' into liam-nested-revocation
blu25 Sep 12, 2024
9de235e
Update spec.bs
blu25 Oct 4, 2024
aabfad3
Merge branch 'master' into liam-nested-revocation
blu25 Nov 1, 2024
2c067b0
address review comments
blu25 Nov 1, 2024
19b33b4
Merge branch 'master' into liam-nested-revocation
blu25 Nov 4, 2024
95cc597
clean up merge issues
blu25 Nov 4, 2024
38d1e66
clean up and move note to definition
blu25 Nov 4, 2024
7a0e92a
Merge branch 'master' into liam-nested-revocation
blu25 Dec 3, 2024
f30fc25
address comments
blu25 Dec 6, 2024
eaf68b0
call out what is being stored in navigablesWithNetworkChildren
blu25 Dec 10, 2024
f476341
address review comments
blu25 Dec 12, 2024
adfb311
address review comments
blu25 Dec 23, 2024
589ca57
add iframe call and run in parallel
blu25 Dec 27, 2024
dfbe2c2
use html element removing steps
blu25 Jan 2, 2025
668de28
address review comments
blu25 Jan 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 150 additions & 47 deletions spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/
urlPrefix: embedder-content-other.html
text: width; url: attr-dim-width
text: height; url: attr-dim-height
urlPrefix: document-lifecycle.html
text: abort a document; url: abort-a-document
blu25 marked this conversation as resolved.
Show resolved Hide resolved
urlPrefix: document-sequences.html
text: browsing context group; url: browsing-context-group
text: browsing context group set; url: browsing-context-group-set
Expand Down Expand Up @@ -144,6 +146,7 @@ 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: completionSteps; url: attempt-to-populate-completion-steps
blu25 marked this conversation as resolved.
Show resolved Hide resolved
text: navigation params; url: navigation-params
text: snapshot source snapshot params; url: snapshotting-source-snapshot-params
text: the navigation must be a replace; url: the-navigation-must-be-a-replace
Expand Down Expand Up @@ -483,8 +486,13 @@ attribute.
</div>

<div algorithm=destroy>
When a <{fencedframe}> element is [=removed from a document=], the user agent <p class=XXX>TODO:
destroy the nested traversable</p>.
When a <{fencedframe}> element is [=removed from a document=], the user agent must run the
following steps:

1. <p class=XXX>TODO: destroy the nested traversable.</p>

1. [=Recalculate the untrusted network status of all fenced frame descendants=] given the
blu25 marked this conversation as resolved.
Show resolved Hide resolved
{{Document}}'s [=node navigable=]'s [=navigable/top-level traversable=].
</div>

The <dfn attribute for=HTMLFencedFrameElement>config</dfn> IDL attribute getter steps are to return
Expand Down Expand Up @@ -849,6 +857,17 @@ a reporting destination=] through the reference it kept, it will handle all of t
stored in the [=list=]. If the destination is never finalized, then the pending events will never
be sent.

An <dfn for=fencedframetype>untrusted network status</dfn> is either "<dfn export for='untrusted
network status'>`enabled`</dfn>", "<dfn export for='untrusted network status'>`disabled for this
tree`</dfn>", or "<dfn export for='untrusted network status'>`disabled for all subtrees`</dfn>".

Note: [=untrusted network status/Disabled for this tree=] is not the final network cutoff state. It
is an intermediate state where the frame has had its network access revoked, but at least one
subframe still has network access. It does not get special API access at this stage as any
blu25 marked this conversation as resolved.
Show resolved Hide resolved
information it gets access to can still be exfiltrated via the subframe with network access. Once
all sub-fenced frames have also had their untrusted network disabled, the fenced frame's status
will switch to the final [=untrusted network status/disabled for all subtrees=] state.

<div algorithm>
In order to <dfn export>finalize a reporting destination</dfn>, given a [=fencedframetype/fenced
frame reporting map=] |reporting map|, a {{FenceReportingDestination}} |destination|, an
Expand Down Expand Up @@ -1224,17 +1243,18 @@ A <dfn export>fenced frame config</dfn> is a [=struct=] with the following [=str
: <dfn for="effective enabled permissions">visibility</dfn>
:: a [=fencedframeconfig/visibility=]

Note: When non-null, this is a [=list=] of [=policy-controlled features=] that the generator of
this config relies on exclusively being enabled inside the <{fencedframe}> that navigates to
this config. Specifically, each feature in this list <span class=allow-2119>must</span> be
enabled by the <{fencedframe}>'s [=fenced navigable container/fenced navigable=]'s
[=Document/permissions policy=]'s [=permissions policy/inherited policy=] when navigating to
this config for the navigation to succeed. The features in this list are not force-enabled, but
rather are used to check that the embedder environment that influences the aforementioned
[=permissions policy/inherited policy=] is relaxed enough to support these essential features.
If the [=inherited policy for a feature|inherited policy value=] for any of these features is
"`Disabled`", the navigation to this config will fail. Any [=policy-controlled feature=] *not*
in this list will not be "`Disabled`" in the <{fencedframe}> that navigates to this config.
Note: When non-null, this is a [=list=] of [=policy-controlled features=] that the generator
of this config relies on exclusively being enabled inside the <{fencedframe}> that navigates
to this config. Specifically, each feature in this list <span class=allow-2119>must</span> be
enabled by the <{fencedframe}>'s [=fenced navigable container/fenced navigable=]'s
[=Document/permissions policy=]'s [=permissions policy/inherited policy=] when navigating to
this config for the navigation to succeed. The features in this list are not force-enabled,
but rather are used to check that the embedder environment that influences the aforementioned
[=permissions policy/inherited policy=] is relaxed enough to support these essential
features. If the [=inherited policy for a feature|inherited policy value=] for any of these
features is "`Disabled`", the navigation to this config will fail. Any [=policy-controlled
feature=] *not* in this list will not be "`Disabled`" in the <{fencedframe}> that navigates
to this config.

: <dfn>fenced frame reporting metadata</dfn>
:: null, or a [=struct=] with the following [=struct/items=]:
Expand Down Expand Up @@ -1266,16 +1286,16 @@ A <dfn export>fenced frame config</dfn> is a [=struct=] with the following [=str
: <dfn>is ad component</dfn>
:: A [=boolean=], initially false.

Note: When true, this [=fenced frame config=] represents an ad component. An ad component can
be used to construct ads composed of multiple pieces. See the <a
href=https://github.com/WICG/turtledove/blob/main/FLEDGE.md#34-ads-composed-of-multiple-pieces>Protected
Audience explainer</a>. For an ad component, event reporting is handled differently. See the <a
href=https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md#support-for-ad-components>Fenced
Frame Ads Reporting explainer</a> that describes this.

: <dfn>cross-origin reporting allowed</dfn>
:: A [=boolean=], initially false.
</dl>

Note: When true, this [=fenced frame config=] represents an ad component. An ad component can be
used to construct ads composed of multiple pieces. See the <a
href=https://github.com/WICG/turtledove/blob/main/FLEDGE.md#34-ads-composed-of-multiple-pieces>Protected
Audience explainer</a>. For an ad component, event reporting is handled differently. See the <a
href=https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md#support-for-ad-components>Fenced
Frame Ads Reporting explainer</a> that describes this.

<h4 id=fenced-frame-config-instance-struct>The [=fenced frame config instance=] [=struct=]</h4>

Expand Down Expand Up @@ -1322,8 +1342,19 @@ A <dfn export>fenced frame config instance</dfn> is a [=struct=] with the follow
: <dfn>is ad component</dfn>
:: A [=boolean=]

: <dfn>has disabled untrusted network</dfn>
:: A [=boolean=], initially false.
: <dfn>untrusted network status</dfn>
:: An [=fencedframetype/untrusted network status=], initially [=untrusted network
status/enabled=].

: <dfn>on network disabled promises</dfn>
:: A [=map=] whose [=map/keys=] are [=global objects=] and [=values=] are [=lists=] of
{{Promise|Promises}}, initially empty.

Note: This stores various {{Promise|Promises}} from various globals that were created during
{{Fence/disableUntrustedNetwork()}}. We store them here so that we can resolve all of them at
once when the <{fencedframe}> and its descendants have their network access fully revoked
blu25 marked this conversation as resolved.
Show resolved Hide resolved
(i.e., the [=fenced frame config instance/untrusted network status=] is [=untrusted network
status/disabled for all subtrees=]).

: <dfn>cross-origin reporting allowed</dfn>
:: A [=boolean=], initially false.
Expand Down Expand Up @@ -1415,8 +1446,11 @@ A <dfn export>fenced frame config instance</dfn> is a [=struct=] with the follow
: [=fenced frame config instance/cross-origin reporting allowed=]
:: |config|'s [=fenced frame config/cross-origin reporting allowed=]

: [=fenced frame config instance/has disabled untrusted network=]
:: false
: [=fenced frame config instance/untrusted network status=]
:: [=untrusted network status/enabled=]

: [=fenced frame config instance/on network disabled promises=]
:: A empty [=map=].
</div>

Each [=browsing context=] has a <dfn for="browsing context">fenced frame config instance</dfn>,
Expand Down Expand Up @@ -1937,8 +1971,11 @@ Several APIs specific to fenced frames are defined on the {{Fence}} interface.

1. Let |p| be [=a new promise=].

1. Let |instance| be [=this=]'s [=relevant global object=]'s [=Window/browsing context=]'s
[=browsing context/fenced frame config instance=].
1. Let |context| be [=this=]'s [=relevant global object=]'s [=Window/browsing context=].

1. If |context| is null, then throw a {{SecurityError}} {{DOMException}}.
domfarolino marked this conversation as resolved.
Show resolved Hide resolved

1. Let |instance| be |context|'s [=browsing context/fenced frame config instance=].

1. If the [=relevant settings object=]'s [=environment settings object/origin=] and
|instance|'s [=fenced frame config instance/mapped url=]'s [=url/origin=] are not [=same
Expand All @@ -1950,32 +1987,92 @@ Several APIs specific to fenced frames are defined on the {{Fence}} interface.

1. Let |global| be [=this=]'s [=relevant global object=].

1. Let |settings| be [=this=]'s [=relevant settings object=].

1. Run the following steps [=in parallel=]:

1. Let |fencedFrameNonce| be |instance|'s [=fenced frame config instance/partition nonce=].

1. Let |credentiallessNonce| be
1. Let |credentiallessNonce| be |global|'s [=page credentialless nonce=].

Issue: the page credentialless nonce
(<a href="https://github.com/WICG/fenced-frame/issues/191">WICG/fenced-frame#191</a>)
1. Invoke [=revoke network for a partition nonce=] on |fencedFrameNonce| with |settings|.

1. Invoke [=revoke network for a partition nonce=] on |fencedFrameNonce|.
1. If |credentiallessNonce| is non-null, invoke [=revoke network for a partition nonce=] on
|credentiallessNonce| with |settings|.

1. Invoke [=revoke network for a partition nonce=] on |credentiallessNonce|.
1. Set |instance|'s [=fenced frame config instance/untrusted network status=] to [=untrusted
network status/disabled for this tree=].

1. Set |instance|'s [=fenced frame config instance/has disabled untrusted network=] to true.
1. Let |promises| be |instance|'s [=fenced frame config instance/on network disabled
promises=].

1. Wait on all nested fenced frames to disable network too.
1. If |promises|[|global|] [=map/exists=], [=list/append=] |p| to |promises|[|global|].

Issue: Spec this waiting more formally.
(<a href="https://github.com/WICG/fenced-frame/issues/151">WICG/fenced-frame#151</a>)
Otherwise, [=map/set=] |promises|[|global|] to the [=list=] « |p| ».

1. [=Queue a global task=] on the [=DOM manipulation task source=] given |global|, to
[=resolve=] |p| with {{undefined}}.
1. [=Recalculate the untrusted network status of all fenced frame descendants=] given
|global|'s [=Window/browsing context=]'s [=browsing context/top-level traversable=].

1. Return |p|.
</div>

<div algorithm>
To <dfn>recalculate the untrusted network status of all fenced frame descendants</dfn> given a
[=top-level traversable=] |topLevelTraversable|, run these steps:

1. [=Assert=]: this is running [=in parallel=].

1. Let |navigables| be |topLevelTraversable|'s [=navigable/active document=]'s
blu25 marked this conversation as resolved.
Show resolved Hide resolved
[=Document/inclusive descendant navigables=] with [=inclusive-dn-unfenced|unfenced=] set to
true.

1. Let |navigablesWithNetworkChildren| be a [=set=] of [=fenced navigable container/fenced
navigables=], initially empty.

1. [=iteration/While=] |navigables| is not [=stack/empty=]:

1. Let |currentNavigable| be the result of [=stack/pop|popping=] from |navigables|.

1. If |currentNavigable| is not a [=fenced navigable container/fenced navigable=], then
[=iteration/continue=].

1. Let |config| be |currentNavigable|'s [=navigable/active browsing context=]'s [=browsing
context/fenced frame config instance=].

1. If |config|'s [=fenced frame config instance/untrusted network status=] is [=untrusted
network status/disabled for all subtrees=], then [=iteration/continue=].

1. Let |networkCutoffReady| be true if |navigablesWithNetworkChildren| does not [=set/contain=]
blu25 marked this conversation as resolved.
Show resolved Hide resolved
|currentNavigable| and |config|'s [=fenced frame config instance/untrusted network status=]
is [=untrusted network status/disabled for this tree=], false otherwise.

Note: A [=fenced navigable container/fenced navigable=] is added to
|navigablesWithNetworkChildren| when it is the unfenced ancestor of another fenced frame
that is determined to not be ready for network cutoff.

1. If |networkCutoffReady| is true:

1. Set |config|'s [=fenced frame config instance/untrusted network status=] to [=untrusted
blu25 marked this conversation as resolved.
Show resolved Hide resolved
network status/disabled for all subtrees=].

1. [=map/For each=] |global| → |promises| in |config|'s [=fenced frame config instance/on
network disabled promises=]:

1. [=list/For each=] |promise| in |promises|:

1. [=Queue a global task=] on the [=DOM manipulation task source=] given |global|, to
[=resolve=] |promise| with {{undefined}}.

1. [=map/Clear=] |config|'s [=fenced frame config instance/on network disabled promises=].

1. Otherwise:
1. Let |ancestorFencedRoot| be |currentNavigable|'s [=traversable navigable/unfenced
parent=]'s [=navigable/traversable navigable=].

1. If |ancestorFencedRoot| is a [=fenced navigable container/fenced navigable=],
[=set/append=] |ancestorFencedRoot| to |navigablesWithNetworkChildren|.
</div>

A user agent has an associated <dfn>network revocation nonce set</dfn>, which is a [=set=] of
[=partition nonces=], and a <dfn>network revocation exemption map</dfn>, which is a [=map=] whose
[=map/keys=] are [=partition nonces=] and [=map/values=] are [=sets=] of [=URLs=].
Expand All @@ -1989,12 +2086,12 @@ Issue: This will require a RFC to add a test-only function to the WPT web driver

<div algorithm>
To <dfn>revoke network for a partition nonce</dfn> using a [=fenced frame config
instance/partition nonce=] |nonce|, run these steps:
instance/partition nonce=] |nonce| given a [=relevant settings object=] |settings|, run these
steps:

1. [=set/Append=] |nonce| to the user agent's [=network revocation nonce set=].

1. [=fetch group/terminated|Terminate=] [=this=]'s [=relevant settings object=]'s
[=fetch/fetch group=].
1. [=fetch group/terminated|Terminate=] |settings|'s [=fetch/fetch group=].
</div>

<div algorithm>
Expand Down Expand Up @@ -2027,8 +2124,14 @@ The network revocation mechanism requires the following monkeypatches to the [[F

Add "[=must be blocked due to a revoked partition nonce=]" to the conditions after
"should request be blocked by Content Security Policy".

Issue: This needs to be passed in both the fenced frame nonce as well as the iframe credentialless
nonce, if it exists.
(<a href="https://github.com/WICG/fenced-frame/issues/191">WICG/fenced-frame#191</a>)
</div>

The network revocation mechanism requires the following monkeypatches to the [[HTML]] Standard.

<h3 id=new-request-destination>New [=request=] [=request/destination=]</h3>

The processing model of a <{fencedframe}>'s navigation request deviates from that of the normal
Expand Down Expand Up @@ -2733,12 +2836,12 @@ the fenced frame boundary, which is a privacy leak. To avoid this, we effectivel
<div algorithm=currently-focused-area-of-a-top-level-traversable>
Modify step 3 of the [=currently focused area of a top-level traversable=] algorithm to read:

3. While |candidate|'s [=focused area=] is either a [=navigable container=] with a non-null
[=navigable container/content navigable=] or a [=fenced navigable container=] with a non-null
[=fenced navigable container/fenced navigable=]: set |candidate| to the [=navigable/active
document=] of either that [=navigable container=]'s [=navigable container/content navigable=]
or that [=fenced navigable container=]'s [=fenced navigable container/fenced navigable=],
whichever is non-null.
3. [=iteration/While=] |candidate|'s [=focused area=] is either a [=navigable container=] with a
non-null [=navigable container/content navigable=] or a [=fenced navigable container=] with a
non-null [=fenced navigable container/fenced navigable=]: set |candidate| to the
[=navigable/active document=] of either that [=navigable container=]'s [=navigable
container/content navigable=] or that [=fenced navigable container=]'s [=fenced navigable
container/fenced navigable=], whichever is non-null.
</div>

<div algorithm=sequential-focus-navigation-patch>
Expand Down Expand Up @@ -2954,7 +3057,7 @@ CORP violation report=] algorithm, as leaving it unfenced may cause a privacy le

1. Let |current navigable| be |sourceDocument|'s [=node navigable=].

1. While |current navigable| is not null:
1. [=iteration/While=] |current navigable| is not null:

1. [=map/iterate|For each=] |type| → |data| of |current navigable|'s [=navigable/active
document=]'s [=Document/automatic beacon data map=]:
Expand Down
Loading