Skip to content

Commit

Permalink
Define Sec-Fetch-Frame-Ancestors.
Browse files Browse the repository at this point in the history
This patch aims to formalize the discussion from
#56, defining a `Sec-Fetch-Frame-Ancestors`
header that supplements `Sec-Fetch-Site`'s exposure of the relationship
between a request's initiator and the request's target with additional
context about the same-siteness of context within which the request was
made. This should support developers' understanding of the viability of
various `SameSite` cookie settings on the one hand, and the ways in
which their resources are partitioned on the other.
  • Loading branch information
mikewest committed Apr 30, 2024
1 parent 8624131 commit d866a02
Showing 1 changed file with 94 additions and 17 deletions.
111 changes: 94 additions & 17 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Abstract:
enough information to make <i lang="la">a priori</i> decisions about whether or not to service
a request based on the way it was made, and the context in which it will be used.
Markup Shorthands: markdown yes
Issue Tracking: Github https://github.com/w3c/webappsec-fetch-metadata/issues/new
!Participate: <a href="https://github.com/w3c/webappsec-fetch-metadata/issues/new">File an issue</a> (<a href="https://github.com/w3c/webappsec-fetch-metadata/issues">open issues</a>)
!Tests: <a href=https://github.com/web-platform-tests/wpt/tree/master/fetch/sec-metadata>web-platform-tests fetch/sec-metadata/</a>
Version History: https://github.com/w3c/webappsec-fetch-metadata/commits/main/index.bs
Expand Down Expand Up @@ -87,11 +88,12 @@ proxies, CDNs, etc) if desired.
Examples {#examples}
--------------------

A request generated by a <{picture}> element would result in a request containing the following
A request generated by a <{picture}> element might result in a request containing the following
HTTP request headers:

```
Sec-Fetch-Dest: image
Sec-Fetch-Frame-Ancestors: cross-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: cross-site
```
Expand Down Expand Up @@ -165,6 +167,69 @@ To <dfn abstract-op lt="set-dest">set the `Sec-Fetch-Dest` header</dfn> for a [=
</div>


The `Sec-Fetch-Frame-Ancestors` HTTP Request Header {#sec-fetch-frame-ancestors-header}
---------------------------------------------------------------------------------------

The <dfn http-header export>`Sec-Fetch-Frame-Ancestors`</dfn> HTTP request header exposes the
relationship between a [=request=]'s initiator's origin, its target origin, and the origins of
the chain of ancestor documents that embed the initiator. It is a [=Structured Header=] whose
value is a [=structured header/token=]. [[!I-D.ietf-httpbis-header-structure]] Its ABNF is:

```
Sec-Fetch-Frame-Ancestors = sh-token
```

Valid `Sec-Fetch-Frame-Ancestors` values include "`cross-site`", "`same-origin`", "`same-site`",
and "`none`". In order to support forward-compatibility with as-yet-unknown request types,
servers SHOULD ignore this header if it contains an invalid value.

Note: This header is delivered for all requests other than top-level navigations. Those are
identifiable by examining the &#96;<a http-header>`Sec-Fetch-Dest`</a>&#96;header's value, so we
can safely omit this header as it would be fully redundant in that case.

<div algorithm="set `Sec-Fetch-Frame-Ancestors`">
To <dfn abstract-op lt="set-frame-ancestors">set the `Sec-Fetch-Frame-Ancestors` header</dfn> for a [=request=] |r|:

<ol class="algorithm">
1. Assert: |r|'s [=request/url=] is a [=potentially trustworthy URL=].

2. If |r|'s [=request/destination=] is "`document`", return.

3. Let |header| be a [=Structured Header=] whose value is a [=structured header/token=].

3. Set |header|'s value to "`same-origin`"..

4. Let |site| be the result of <a abstract-op lt="determine-site">determining |r|'s site value</a>.

5. Switch on |site|, and run the associated steps:

: "`none`"
:: Set |header|'s value to "`none`".
: "`cross-site`"
:: Set |header|'s value to "`cross-site`".
: "`same-site`"
: "`same-origin`"
:: For each |ancestor| in |r|'s [=request/client=]'s [=environment settings object/global object=]'s
[=associated `Document`=]'s [=Document/inclusive ancestor navigables=]:

1. Let |ancestor origin| be |ancestor|'s [=navigable/active document=]'s [=Document/origin=].

2. If |ancestor origin| is not [=same site=] with |r|'s [=request/origin=], set |header|'s value
to "`cross-site`", and [=iteration/break=].

3. If |ancestor origin| is not [=same origin=] with |r|'s [=request/origin=], set |header|'s value
to "`same-site`", and [=iteration/break=].

Note: We're relying on the fact that <a abstract-op lt='determine-site'>determine a request's site value</a> walks the
redirect chain, and the output can be "`same-site`" or "`same-origin`" only in cases where the
request's client is same-origin or same-site with each item in the chain. The only things we
need to compare, then, are the ancestor chain and the request's request/origin.

6. [=header list/Set a structured field value=]
&#96;<a http-header>`Sec-Fetch-Frame-Ancestors`</a>&#96;/|header| in |r|'s [=request/header list=].
</ol>
</div>


The `Sec-Fetch-Mode` HTTP Request Header {#sec-fetch-mode-header}
-----------------------------------------------------------------
Expand Down Expand Up @@ -212,33 +277,43 @@ Valid `Sec-Fetch-Site` values include "`cross-site`", "`same-origin`", "`same-si
In order to support forward-compatibility with as-yet-unknown request types, servers SHOULD ignore
this header if it contains an invalid value.

<div algorithm="set `Sec-Fetch-Site`">
To <dfn abstract-op lt="set-site">set the `Sec-Fetch-Site` header</dfn> for a [=request=] |r|:
<div algorithm="determine request's site">
To <dfn abstract-op lt="determine-site">determine a request's site value</dfn> for a [=request=] |r|:

<ol class="algorithm">
1. Assert: |r|'s [=request/url=] is a [=potentially trustworthy URL=].

2. Let |header| be a [=Structured Header=] whose value is a [=structured header/token=].

3. Set |header|'s value to `same-origin`.
1. Let |result| be "`same-origin`".

4. If |r| is a [=navigation request=] that was explicitly caused by a user's interaction with
2. If |r| is a [=navigation request=] that was explicitly caused by a user's interaction with
the user agent (by typing an address into the user agent directly, for example, or by
clicking a bookmark, etc.), then set |header|'s value to `none`.
clicking a bookmark, etc.), then set |result| to "`none`".

Note: See [[#directly-user-initiated]] for more detail on this somewhat poorly-defined step.

5. If |header|'s value is not `none`, then for each |url| in |r|'s [=request/url list=]:
3. If |result| is not "`none`", then for each |url| in |r|'s [=request/url list=]:

1. If |url| is [=same origin=] with |r|'s [=request/origin=], [=iteration/continue=].

2. Set |header|'s value to `cross-site`.
2. Set |result| to "`cross-site`".

3. If |r|'s [=request/origin=] is not [=same site=] with |url|'s [=url/origin=], then [=iteration/break=].

4. Set |header|'s value to `same-site`.
4. Set |result| to "`same-site`".

6. [=header list/Set a structured field value=]
4. Return |result|.
</ol>
</div>

<div algorithm="set `Sec-Fetch-Site`">
To <dfn abstract-op lt="set-site">set the `Sec-Fetch-Site` header</dfn> for a [=request=] |r|:

<ol class="algorithm">
1. Assert: |r|'s [=request/url=] is a [=potentially trustworthy URL=].

2. Let |header| be a [=Structured Header=] whose value is a [=structured header/token=].

3. Set |header|'s value to the result of <a abstract-op lt="determine-site">determining |r|'s site value</a>.

4. [=header list/Set a structured field value=]
&#96;<a http-header>`Sec-Fetch-Site`</a>&#96;/|header| in |r|'s [=request/header list=].
</ol>
</div>
Expand Down Expand Up @@ -298,11 +373,13 @@ To <dfn abstract-op export>append the Fetch metadata headers for a request</dfn>

2. <a abstract-op lt='set-dest'>Set the `Sec-Fetch-Dest` header</a> for |r|.

3. <a abstract-op lt='set-mode'>Set the `Sec-Fetch-Mode` header</a> for |r|.
3. <a abstract-op lt='set-frame-ancestors'>Set the `Sec-Fetch-Frame-Ancestors` header</a> for |r|.

4. <a abstract-op lt='set-mode'>Set the `Sec-Fetch-Mode` header</a> for |r|.

4. <a abstract-op lt='set-site'>Set the `Sec-Fetch-Site` header</a> for |r|.
5. <a abstract-op lt='set-site'>Set the `Sec-Fetch-Site` header</a> for |r|.

5. <a abstract-op lt='set-user'>Set the `Sec-Fetch-User` header</a> for |r|.
6. <a abstract-op lt='set-user'>Set the `Sec-Fetch-User` header</a> for |r|.
</ol>
</div>

Expand Down

0 comments on commit d866a02

Please sign in to comment.