From ba63b10f3f7f2bcc97378b20ef5908582dbb173d Mon Sep 17 00:00:00 2001 From: Tsuyoshi Horo Date: Wed, 4 Dec 2019 10:54:01 +0900 Subject: [PATCH 1/6] Add two explainers of subresource signed exchanges I uploaded explainer documents of subresource signed exchanges to my repository (https://github.com/horo-t/subresource-signed-exchange). But they should be in this webpackage repository. So this patch copies them from "horo-t/subresource-signed-exchange" repository. Spec issue: https://github.com/WICG/webpackage/issues/347 TAG review: https://github.com/w3ctag/design-reviews/issues/352 --- ...igned-exchange-alternate-link-explainer.md | 164 ++++++++++++++++++ ...hange-subresource-subtitution-explainer.md | 155 +++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 explainers/signed-exchange-alternate-link-explainer.md create mode 100644 explainers/signed-exchange-subresource-subtitution-explainer.md diff --git a/explainers/signed-exchange-alternate-link-explainer.md b/explainers/signed-exchange-alternate-link-explainer.md new file mode 100644 index 00000000..a26b2859 --- /dev/null +++ b/explainers/signed-exchange-alternate-link-explainer.md @@ -0,0 +1,164 @@ +# Signed Exchange alternate link +## Introduction +We want to extend the usage of the existing [rel=alternate](https://html.spec.whatwg.org/multipage/links.html#rel-alternate) link header for signed exchange. Using this link header, the content publishers can declare that the resource is available in signed exchange format. This can be used both by the crawlers of aggregator sites (SNS, News site, search engine..) and by the UAs. The crawlers can cache and serve the signed exchange of the content in their own server. The UAs can provide the users with a way to save the page in signe exchange format. And also signed exchange alternate links can be used to recursively prefetch appropriate subresource signed exchanges while prefetching the main resource signed exchange. + +## Use Cases +### Signed Exchange discovery of main resource +1. Content publishers can declare the URL of signed exchange format of the content using an alternate link HTTP header or using an alternate link HTML element. + - Example of signed exchange alternate link HTTP header in the HTTP response headers of the main resource of the content (https://publisher.example/article.html): + ``` + Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + anchor="https://publisher.example/article.html" + ``` + - Example of signed exchange alternate link HTML element in the main resource of the content (https://publisher.example/article.html): + ``` + + ``` +1. This signed exchange alternate link of main resource can be used both by the crawlers and the UAs. + - When the crawlers detects the signed exchange alternate link, the crawlers can fetch the signed exchange. And when a user is browsing the aggregator site (https://feed.example) and it has a link to the article, the signed exchange can be used for [privacy-preserving prefetching](https://wicg.github.io/webpackage/draft-yasskin-webpackage-use-cases.html#private-prefetch) using a prefetch `` element and `` link to the signed exchange . + ``` + + feed.example + ``` + - While the user of the UA is browsing an article (article.html), and if there is a signed exchange alternate link, the UA can provide the user with a way to save the page in signe exchange format. The saved file can be used to share with other users. + +### Recursive subresource signed exchange prefetch +1. A crawler of an aggregator site fetches an article (https://publisher.example/article.html). +1. There is an alternate link of signed exchange of the article in the response header: + ``` + Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + anchor="https://publisher.example/article.html" + ``` +1. The crawler fetches and verifies the signed exchange (article.html.sxg). + + 1. The response from the server has an alternate link of subresource signed exchange: + ``` + Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + anchor="https://cdn.publisher.example/lib.js" + ``` + 1. And the inner response of the main resource signed exchange (article.html.sxg) has a preload header and an [allowed-alt-sxg header](./signed-exchange-subresource-subtitution-explainer.md): + ``` + Link: ; + rel="preload"; + as="script" + Link: ; + rel="allowed-alt-sxg"; + header-integrity="sha256-XXXXXX" + ``` +1. The crawler fetches and verifies the subresource signed exchange (lib.js.sxg). +1. The aggregator site will serve the signed exchanges (article.html.sxg and lib.js.sxg) from their own server. + +1. While a user is browsing the aggregator site (https://feed.example), a prefetch link element is inserted because the use is likely to want to read the article. + ``` + + ``` +1. The UA prefetches the signed exchange (article.html.sxg). + 1. The response from the server has an alternate link of subresource signed exchange: + ``` + Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + anchor="https://cdn.publisher.example/lib.js" + ``` + 1. And the inner response of the main resource signed exchange (article.html.sxg) has a preload header and an allowed-alt-sxg header: + ``` + Link: ; + rel="preload"; + as="script" + Link: ; + rel="allowed-alt-sxg"; + header-integrity="sha256-XXXXXX" + ``` +1. The UA recursively prefetches lib.js.sxg. +1. If the user clicks a link the article’s signed exchange, both the main resource of the article and the script are loaded from the prefetched signed exchanges. + +## Proposal +While processing preload link HTTP headers in prefetched main resource signed exchange’s inner response: +1. Check whether matching “allowed-alt-sxg” link HTTP header in the inner response exists or not. (Note that if the allowed-alt-sxg link HTTP header has variants and variant-key attributes, the UA must execute the algorithm written in [HTTP Representation Variants](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) spec to find the matching header.) +1. If exists, check whether matching “alternate” link HTTP header in the outer response exists or not. +1. If exists, prefetches the matching signed exchange instead of prefetching the original resource URL. +1. The prefetched signed exchange will be stored to the SignedExchangeCache of the Document. And it will be passed to the next Document and used while processing the preload link header. This behavior is written in [Signed Exchange subresource substitution explainer](./signed-exchange-subresource-subtitution-explainer.md). + +## Detailed design discussion +### Content negotiation using Variants and Variant-Key +The **alternate** link header and **allowed-alt-sxg** link headers can have [variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) attributes to support content negotiation (eg: [WebP support](https://developers.google.com/speed/webp/faq#server-side_content_negotiation_via_accept_headers)). + +- In **outer** HTTP response of article.html.sxg from feed.example: + ``` + Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/jpeg"; + anchor="https://publisher.example/image"; + Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/webp"; + anchor="https://publisher.example/image"; + ``` +- In **inner** response header of article.html.sxg: + ``` + Link: ; + rel="allowed-alt-sxg"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/jpeg"; + header-integrity="sha256-AAA" + Link: ; + rel="allowed-alt-sxg"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/webp"; + header-integrity="sha256-BBB" + Link: ; rel=preload; as=image; + ``` +If a UA supports WebP, the UA should prefetch **image_webp.sxg** which content is WebP format. Otherwise the UA should prefetch **image_jpeg.sxg** which content is JPEG format. + +## Security and Privacy Considerations +The UA must fetch the alternate signed exchange subresource (lib.js.sxg) even if there is the original subresource (lib.js) in the HTTPCache. Otherwise it leaks the state of publisher’s site to the distributor of the signed exchange. + +## [Self-Review Questionnaire: Security and Privacy](https://www.w3.org/TR/security-privacy-questionnaire/) +1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? + - The existence of the alternative signed exchange in HTTP Cache is exposed. +1. Is this specification exposing the minimum amount of information necessary to power the feature? + - Yes. +1. How does this specification deal with personal information or personally-identifiable information or information derived thereof? + - Signed Exchange should not include personal information. +1. How does this specification deal with sensitive information? + - Signed Exchange should not include sensitive information. +1. Does this specification introduce new state for an origin that persists across browsing sessions? + - No. The prefetched signed exchange is stored to HTTPCache. But this is the existing behavior when directly prefetching the signed exchange using ``. +1. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? + - This exposes whether the UA support this feature or not. +1. Does this specification allow an origin access to sensors on a user’s device + - No +1. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. + - The existence of the alternative signed exchange in HTTP Cache is exposed. + - But this is the same as the existing behavior when directly prefetching the signed exchange using ``. +1. Does this specification enable new script execution/loading mechanisms? + - No +1. Does this specification allow an origin to access other devices? + - No +1. Does this specification allow an origin some measure of control over a user agent’s native UI? + - No +1. What temporary identifiers might this this specification create or expose to the web? + - No +1. How does this specification distinguish between behavior in first-party and third-party contexts? + - This feature should work well with third-party signed exchange. + - To avoid leaking the state of publisher’s site to the distributor of the signed exchange, the UA must fetch the alternate signed exchange subresource even if there is the original subresource in the HTTPCache. +1. How does this specification work in the context of a user agent’s Private \ Browsing or "incognito" mode? + - No difference while the user is browsing sites in Private mode. +1. Does this specification have a "Security Considerations" and "Privacy Considerations" section? + - Yes +1. Does this specification allow downgrading default security characteristics? + - No diff --git a/explainers/signed-exchange-subresource-subtitution-explainer.md b/explainers/signed-exchange-subresource-subtitution-explainer.md new file mode 100644 index 00000000..c5878c55 --- /dev/null +++ b/explainers/signed-exchange-subresource-subtitution-explainer.md @@ -0,0 +1,155 @@ +# Signed Exchange subresource substitution + +## Introduction + +We want to introduce a new **rel=allowed-alt-sxg** link HTTP header which will be used along with rel=preload link HTTP header. By using this header, content publishers can declare that the UA can load the specific subresources from cached signed exchanges which were prefetched in the referrer page. + +## Use Cases + +### Privacy-preserving prefetching subresources + +A user is browsing a news feed site (https://feed.example/). The user clicks a link to an article in another site (https://publisher.example/article.html). The article is using a large JS library (https://cdn.publisher.example/lib.js) and the user must wait for the JS file to be fetched from the server to read the article. + +If the feed site knows that the article is depending on the JS file, the site can insert a link element (``) to prefetch the JS file while the user is browsing the feed site. But this is problematic from the privacy point of view. And also this doesn’t work if the UA is using [origin isolated HTTPCache mechanism](http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html). + +Signed Exchange has solved this [privacy-preserving prefetching](https://wicg.github.io/webpackage/draft-yasskin-webpackage-use-cases.html#private-prefetch) problem for main resources. If the publisher is providing the article in signed exchange format (article.html.sxg), the UA can prefetch the signed exchange from the feed site’s own server while the user is browsing the feed site. But there is no way to prefetch subresources in a privacy-preserving manner yet. + +Our proposal can solve this problem: +1. The publisher provides the script file in signed exchange format (lib.js.sxg) along with its [header integrity value](#header-integrity-of-signed-exchange). +1. The UA prefetches the signed exchange of the script from the feed site’s own server while the user is browsing the feed site. +1. The HTTP response of the article from the publisher's server (https://publisher.example/article.html) has an allowed-alt-sxg link header to declare that the UA can load the script from the prefetched signed exchange. + ``` + Link: ; + rel="allowed-alt-sxg"; + header-integrity="sha256-..." + ``` + So, the UA can load the JS file from the prefetched signed exchange. If the publisher is providing the article in signed exchange format (article.html.sxg), the allowed-alt-sxg link header is in the inner response headers of the signed exchange. + +### Reading article while offline +If the publisher is providing the main resource and necessary subresources in signed exchange format, the user of the news feed site can read the article even while offline. This can be done using Service Worker. +1. The Service Worker of the news feed site fetches the main resource signed exchange and subresources signed exchanges (maybe using [Background Fetch](https://wicg.github.io/background-fetch/)) while online, and stores them to the CacheStorage of the feed site origin. +1. While the user is browsing the feed site, the site inserts prefetch link elements to prefetch the signed exchanges. The service worker responds to the fetch events of the prefetch with the signed exchanges in the CacheStorage. +1. When the user clicks a link to the article’s signed exchange, the content and all necessary subresources are loaded from the cached signed exchange. So the user can read the article while offline. + + +# Proposal + +1. Introduce SignedExchangeCache and PrefetchedSignedExchangeCache which are attached to a Document. SignedExchangeCache keeps the signed exchanges which are prefetched from the Document. PrefetchedSignedExchangeCache keeps the signed exchanges which were passed from the referrer Document which triggered the navigation to the current Document. +1. While processing "[prefetch](https://html.spec.whatwg.org/multipage/links.html#link-type-prefetch)" link (eg: ``): + - If succeeded prefetching the signed exchange (including merkle integrity check of the body), stores the parsedExchange which is the result of [parsing a signed exchange](https://wicg.github.io/webpackage/loading.html#ref-for-parsing-a-signed-exchange) (= inner request URL and inner response) to the SignedExchangeCache. +1. While [navigating across documents](https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigating-across-documents), copy the parsedExchanges in the SignedExchangeCache of the source document to the PrefetchedSignedExchangeCache of the target document. This is intended to provide a way to pass the cached signed exchange across origins even if the UA is using origin isolated HTTPCache mechanism. +1. While processing [preload](https://html.spec.whatwg.org/multipage/links.html#link-type-preload) link HTTP headers (eg: Link: ; rel="preload"; as="script"): + - Check whether matching "allowed-alt-sxg" link HTTP header (`Link: ;rel="allowed-alt-sxg";header-integrity="sha256-.."`) exists or not. (Note that if the allowed-alt-sxg link HTTP header has variants and variant-key attributes, the UA must execute the algorithm written in [HTTP Representation Variants spec](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) to find the matching header.) + - Check whether all preload links which have matching allowed-alt-sxg link header have matching (url and header-integrity) parsedExchange in PrefetchedSignedExchangeCache. If the check passes, set request's stashed exchange to the parsedExchange so the resource will be loaded from the cached signed exchange. + - After processing the link HTTP headers, clears the PrefetchedSignedExchangeCache. + +# Detailed design discussion +## Header integrity of signed exchange +We use the SHA256 hash value of *signedHeaders* in [application/signed-exchange format](https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange) for integrity checking. This signedHeaders is *"the canonical serialization of the CBOR representation of the response headers of the exchange represented by the application/signed-exchange resource, excluding the Signature header field"*. So this value doesn’t change even if the publisher signs the content again or changes the signing key. This header-integrity value can verify the integrity of both the response header and the content body, because signed exchange’s response header must have digest header. + +The UA needs to check that this value of the prefetched subresource signed exchange is same as the header-integrity attribute of allowed-alt-sxg link header in the response from the publisher. This is intended to prevent the distributor from encoding a tracking ID into the subresource signed exchange. + +We can’t use the [SRI’s integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) for this purpose, because SRI’s integrity can be used only for verifying the integrity of the content body. So if the UA use the SRI’s integrity value in allowed-alt-sxg link header, we can use the subresource signed exchanges to track the users by changing content-type and detecting the image loading failure. + +## Multiple subresource signed exchanges +If there are multiple matching subresource signed exchanges (example: script.js.sxg and image.jpg.sxg), the UA must check that there is no error in the all signed exchanges (eg: sig matching, URL matching, Merkle Integrity error) before processing the content of the signed exchanges. This is intended to prevent the distributor from encoding a tracking ID into the set of subresources it prefetches. this means that the UA can use the subresource signed exchanges only when they are defined in the header. + +## Can’t we have a global SignedExchangeCache? +If we can have a global SignedExchangeCache, we can use the all signed exchanges which have previously prefetched, even if they are not prefetched by the referrer page. This can +improve the performance. But this introduces privacy issues such as [Timing Leaks](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#cache_timing) and [Deterministic History Leaks](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#history_leaks) described in [the document about Subresource Integrity Addressable Caching](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html). + +To avoid these privacy issues, we introduced the limitation that we can only use the signed exchanges which were prefetched by the referrer page. + +## Can’t we merge allowed-alt-sxg to preload header? +If we can declare the header-integrity value in the existing preload link HTTP header, we don’t need to introduce a new "allowed-alt-sxg" link HTTP header. But it becomes complicated when supporting the [imagesrcset attribute of preload link](https://github.com/w3c/preload/issues/120). + +For Example: +``` +Link: ; + rel="preload"; + as="image"; + imagesrcset="https://publisher.example/wide.jpg 640w, + https://publisher.example/narrow.jpg 320w"; + imagesizes="(max-width: 640px) 100vw, 640px" +``` +In this case, we want to declare that both wide.jpg and narrow.jpg can be loaded from signed exchanges and the header-integrity is sha256-XXX and sha256-YYY. But how to express in this preload link header? + +In our proposal, we can have two allowed-alt-sxg link headers. +``` +Link: ; + rel="allowed-alt-sxg"; + header-integrity="sha256-XXX" +Link: ; + rel="allowed-alt-sxg"; + header-integrity="sha256-YYY" +``` + +## Lifetime of the entry in SignedExchangeCache +The UA must check both the [signature expire time](https://wicg.github.io/webpackage/loading.html#exchange-signature-expiration-time) of the signed exchange and Cache-Control header of the outer response. The UA may discard the entry if it is expired. + +## Content negotiation using Variants and Variant-Key +The **allowed-alt-sxg** link headers can have [variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) attributes to support content negotiation (eg: [WebP support](https://developers.google.com/speed/webp/faq#server-side_content_negotiation_via_accept_headers)). +``` +Link: ; + rel="allowed-alt-sxg"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/jpeg"; + header-integrity="sha256-AAA" +Link: ; + rel="allowed-alt-sxg"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/webp"; + header-integrity="sha256-BBB" +Link: ; rel=preload; as=image; +``` +If a UA supports WebP format, the UA can use the signed exchange which header-integrity is sha256-BBB if available in the cache. Otherwise the UA can use the signed exchange which header-integrity is sha256-AAA if available in the cache. + +If the sha256-AAA signed exchange exists in the cache but the sha256-BBB signed exchange doesn’t exists, the UA which supports WebP format MUST ignore the sha256-AAA signed exchange and fetch the original URL. Otherwise this can be used for sending tracking ID. + +## Security and Privacy Considerations +- The publishers can know whether the referrer page has prefetched the signed exchange subresources or not by checking the resource timing information. But this only exposes 1 bit information (= yes or no) because UAs can use the cached signed exchange only if the required signed exchanges are all available. +- The UA can use the prefetched signed exchange subresources, only when they were prefetched in the referrer page. This is intended to avoid leaking the prefetching state to succeeding pages. +- The UA check the header integrity value, so the distributor of the subresource signed exchange can’t inject arbitrary resources to the publisher’s page. This prevents distributors from sending tracking IDs to the publisher’s page. +- The UA need to check both [the request URL](https://wicg.github.io/webpackage/loading.html#exchange-request-url) and the header integrity value of the signed exchange to avoid [Origin Laundering](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#origin_laundering) attack. The URL is not in signedHeaders, so the header integrity value can’t check the URL is correct. +- The UA must fetch the signed exchange subresource (https://cdn.feed.example/cdn.publisher.example/lib.js.sxg) while processing the prefetch link element (``) even if there is the original subresource (http://cdn.publisher.example/lib.js) in the HTTPCache. Otherwise it leaks the state of publisher’s site to the distributor of the signed exchange. +- The UA must ignore the not-yet-completed subresource signed exchange prefetch to prevent distributors from interfering the publisher’s page. (Eg. Intentionally block or delay the subresource loading.) So if the user clicks the link to the article while the UA is still prefetching the subresource signed exchange, the UA must fetch the subresource from the original URL after navigation. +- The UA can use the prefetched signed exchange subresources only if the preload HTTP link headers for the subresources exist in the response headers. It is because the UA need to check the availability of all required signed exchanges before start loading subresources. + +## [Self-Review Questionnaire: Security and Privacy](https://www.w3.org/TR/security-privacy-questionnaire/) +1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? + - This feature exposes the 1 bit information "the referrer page has prefetched the signed exchange subresources or not" to the publisher. +1. Is this specification exposing the minimum amount of information necessary to power the feature? + - Yes. This proposal has limitations such as "all subresource SXG must be finished prefetching, otherwise ignored", "subresource SXG must be prefetched even if the original subresource exists in HTTPCache". +1. How does this specification deal with personal information or personally-identifiable information or information derived thereof? + - Signed Exchange should not include personal information. +1. How does this specification deal with sensitive information? + - Signed Exchange should not include sensitive information. +1. Does this specification introduce new state for an origin that persists across browsing sessions? + - No. The prefetched signed exchange subresources can be used only from the pages which are navigated from the document which prefetched them. +1. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? + - This exposes whether the UA support this feature or not. +1. Does this specification allow an origin access to sensors on a user’s device + - No +1. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. + - This feature exposes the 1 bit information "the referrer page has prefetched the signed exchange subresources or not" to the publisher. + - Sending 1 bit information from the distributor to the publisher is already easily possible just by changing the URL. +1. Does this specification enable new script execution/loading mechanisms? + - This specification introduces a new script loading path, from prefetched signed exchange. The existing security checks such as CSP/CORP must be applied as if the script is loaded from the original URL. +1. Does this specification allow an origin to access other devices? + - No +1. Does this specification allow an origin some measure of control over a user agent’s native UI? + - No +1. What temporary identifiers might this this specification create or expose to the web? + - No +1. How does this specification distinguish between behavior in first-party and third-party contexts? + - This feature treats all entities (the distributor of signed exchange, the publisher site, the origin of subresource URL) as third-party origins. + - To avoid leaking user-specific data in the distributor of signed exchange, the prefetch request must not contain credentials. This is covered by the "Prefetch and double-key caching" issue. + - The origin of subresource URL could be different from the origin of publisher site. The cross origin security checks (CORS/CORB/CORP/..) must be executed while reading the response from the cached signed exchanges. +1. How does this specification work in the context of a user agent’s Private \ Browsing or "incognito" mode? + - No difference while the user is browsing sites in Private mode. + - If the user opens a link in private mode while browsing in normal mode (eg: "Open link in incognito window"), the prefetched signed exchanges must be ignored. +1. Does this specification have a "Security Considerations" and "Privacy Considerations" section? + - Yes +1. Does this specification allow downgrading default security characteristics? + - No + From 3a44a08be4274f3e0606c13486042bbe89c6e643 Mon Sep 17 00:00:00 2001 From: Tsuyoshi Horo Date: Thu, 5 Dec 2019 18:38:00 +0900 Subject: [PATCH 2/6] Incorporated jyasskin's comment --- ...igned-exchange-alternate-link-explainer.md | 223 ++++++++------ ...hange-subresource-subtitution-explainer.md | 282 ++++++++++++++---- 2 files changed, 345 insertions(+), 160 deletions(-) diff --git a/explainers/signed-exchange-alternate-link-explainer.md b/explainers/signed-exchange-alternate-link-explainer.md index a26b2859..084c2b6e 100644 --- a/explainers/signed-exchange-alternate-link-explainer.md +++ b/explainers/signed-exchange-alternate-link-explainer.md @@ -1,97 +1,97 @@ # Signed Exchange alternate link ## Introduction -We want to extend the usage of the existing [rel=alternate](https://html.spec.whatwg.org/multipage/links.html#rel-alternate) link header for signed exchange. Using this link header, the content publishers can declare that the resource is available in signed exchange format. This can be used both by the crawlers of aggregator sites (SNS, News site, search engine..) and by the UAs. The crawlers can cache and serve the signed exchange of the content in their own server. The UAs can provide the users with a way to save the page in signe exchange format. And also signed exchange alternate links can be used to recursively prefetch appropriate subresource signed exchanges while prefetching the main resource signed exchange. +We want to allow the publisher of a resource to declare that a signed exchange +is available holding the content of either that resource or one of its +subresources. We expect aggregator sites (social networks, News site, search +engine..) to use this to cache the signed version of a resource in order to +serve it to their users. We expect UAs to use this to allow users to save the +page in signed exchange format. When the publisher identifies a same-origin +signed exchange for a cross-origin subresource, the UA can use that information +to recursively prefetch the subresource without exposing its speculative +activity across origins. + +[``](https://html.spec.whatwg.org/multipage/links.html#rel-alternate) +and the equivalent `Link` header are already defined to declare that the +referenced document is a reformulation of the current document as a signed +exchange. To offer signed exchanges for subresources, we propose to use the +[`anchor` parameter](https://tools.ietf.org/html/rfc8288#section-3.2) to +identify the replaced subresource. This may be the first use of the `anchor` +parameter in the web platform. -## Use Cases -### Signed Exchange discovery of main resource -1. Content publishers can declare the URL of signed exchange format of the content using an alternate link HTTP header or using an alternate link HTML element. - - Example of signed exchange alternate link HTTP header in the HTTP response headers of the main resource of the content (https://publisher.example/article.html): - ``` - Link: ; - rel="alternate"; - type="application/signed-exchange;v=b3"; - anchor="https://publisher.example/article.html" - ``` - - Example of signed exchange alternate link HTML element in the main resource of the content (https://publisher.example/article.html): - ``` - - ``` -1. This signed exchange alternate link of main resource can be used both by the crawlers and the UAs. - - When the crawlers detects the signed exchange alternate link, the crawlers can fetch the signed exchange. And when a user is browsing the aggregator site (https://feed.example) and it has a link to the article, the signed exchange can be used for [privacy-preserving prefetching](https://wicg.github.io/webpackage/draft-yasskin-webpackage-use-cases.html#private-prefetch) using a prefetch `` element and `` link to the signed exchange . - ``` - - feed.example - ``` - - While the user of the UA is browsing an article (article.html), and if there is a signed exchange alternate link, the UA can provide the user with a way to save the page in signe exchange format. The saved file can be used to share with other users. +## Use Cases ### Recursive subresource signed exchange prefetch -1. A crawler of an aggregator site fetches an article (https://publisher.example/article.html). -1. There is an alternate link of signed exchange of the article in the response header: - ``` - Link: ; - rel="alternate"; - type="application/signed-exchange;v=b3"; - anchor="https://publisher.example/article.html" - ``` -1. The crawler fetches and verifies the signed exchange (article.html.sxg). - - 1. The response from the server has an alternate link of subresource signed exchange: - ``` - Link: ; - rel="alternate"; - type="application/signed-exchange;v=b3"; - anchor="https://cdn.publisher.example/lib.js" - ``` - 1. And the inner response of the main resource signed exchange (article.html.sxg) has a preload header and an [allowed-alt-sxg header](./signed-exchange-subresource-subtitution-explainer.md): - ``` - Link: ; - rel="preload"; - as="script" - Link: ; - rel="allowed-alt-sxg"; - header-integrity="sha256-XXXXXX" - ``` -1. The crawler fetches and verifies the subresource signed exchange (lib.js.sxg). -1. The aggregator site will serve the signed exchanges (article.html.sxg and lib.js.sxg) from their own server. - -1. While a user is browsing the aggregator site (https://feed.example), a prefetch link element is inserted because the use is likely to want to read the article. +While a user is browsing an aggregator site (https://feed.example), the +aggregator guesses that the user is likely to want to read a particular article +(https://publisher.example/article.html) and so inserts a prefetch link pointing +to a signed exchange version of that article. ``` ``` -1. The UA prefetches the signed exchange (article.html.sxg). - 1. The response from the server has an alternate link of subresource signed exchange: - ``` - Link: ; - rel="alternate"; - type="application/signed-exchange;v=b3"; - anchor="https://cdn.publisher.example/lib.js" - ``` - 1. And the inner response of the main resource signed exchange (article.html.sxg) has a preload header and an allowed-alt-sxg header: - ``` - Link: ; - rel="preload"; - as="script" - Link: ; - rel="allowed-alt-sxg"; - header-integrity="sha256-XXXXXX" - ``` -1. The UA recursively prefetches lib.js.sxg. -1. If the user clicks a link the article’s signed exchange, both the main resource of the article and the script are loaded from the prefetched signed exchanges. +When the UA prefetches the signed exchange (article.html.sxg), the aggregator +server includes a declaration that one of `article.html`'s subresources +(https://cdn.publisher.example/lib.js) is also available from the same +aggregator. + +The response from the server has an alternate link of subresource signed +exchange: + +``` +Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + anchor="https://cdn.publisher.example/lib.js" +``` + +To prevent an attacker from loading an incompatible version of the subresource, +the resource _inside_ the signed exchange has to identify the exact version of +the replacement signed exchange using a `Link: ... rel="allowed-alt-sxg"` with +the hash of the signed headers (which themselves include a hash of the content). + +To prevent a tracker from conveying a user ID in their choice of which +subresources to prefetch, the inner resource has to preload the same +subresources that the aggregator prefetches. +And the inner response of the main resource signed exchange (article.html.sxg) +has a preload header and an allowed-alt-sxg header: + +``` +Link: ; + rel="preload"; + as="script" +Link: ; + rel="allowed-alt-sxg"; + header-integrity="sha256-XXXXXX" +``` + +The UA recursively prefetches lib.js.sxg. + +If the user navigates to the expected article, both the main resource of the +article and the script subresource are loaded from the prefetched signed +exchanges. ## Proposal -While processing preload link HTTP headers in prefetched main resource signed exchange’s inner response: -1. Check whether matching “allowed-alt-sxg” link HTTP header in the inner response exists or not. (Note that if the allowed-alt-sxg link HTTP header has variants and variant-key attributes, the UA must execute the algorithm written in [HTTP Representation Variants](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) spec to find the matching header.) -1. If exists, check whether matching “alternate” link HTTP header in the outer response exists or not. -1. If exists, prefetches the matching signed exchange instead of prefetching the original resource URL. -1. The prefetched signed exchange will be stored to the SignedExchangeCache of the Document. And it will be passed to the next Document and used while processing the preload link header. This behavior is written in [Signed Exchange subresource substitution explainer](./signed-exchange-subresource-subtitution-explainer.md). +While prefetching a HTML resource in signed exchange format: + +1. Whent the UA detects a "preload" link HTTP header in the inner response, +check whether matching “allowed-alt-sxg” link HTTP header in the inner response +exists or not. (Note that if the allowed-alt-sxg link HTTP header has variants +and variant-key attributes, the UA must execute the algorithm written in +[HTTP Representation Variants](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) +spec to find the matching header.) +1. If exists, check whether matching “alternate” link HTTP header in the outer +response exists or not. +1. If exists, prefetches the matching signed exchange instead of prefetching the +original resource URL. +1. The prefetched signed exchange will be stored to the SignedExchangeCache of +the Document. And it will be passed to the next Document and used while +processing the preload link header. This behavior is written in +[Signed Exchange subresource substitution explainer](./signed-exchange-subresource-subtitution-explainer.md). -## Detailed design discussion -### Content negotiation using Variants and Variant-Key -The **alternate** link header and **allowed-alt-sxg** link headers can have [variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) attributes to support content negotiation (eg: [WebP support](https://developers.google.com/speed/webp/faq#server-side_content_negotiation_via_accept_headers)). +## Content negotiation using Variants and Variant-Key +The **alternate** link header and **allowed-alt-sxg** link headers can have +[variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) +attributes to support content negotiation (eg: +[WebP support](https://developers.google.com/speed/webp/faq#server-side_content_negotiation_via_accept_headers)). - In **outer** HTTP response of article.html.sxg from feed.example: ``` @@ -122,43 +122,68 @@ The **alternate** link header and **allowed-alt-sxg** link headers can have [var header-integrity="sha256-BBB" Link: ; rel=preload; as=image; ``` -If a UA supports WebP, the UA should prefetch **image_webp.sxg** which content is WebP format. Otherwise the UA should prefetch **image_jpeg.sxg** which content is JPEG format. +If a UA supports WebP, the UA should prefetch **image_webp.sxg** which content +is WebP format. Otherwise the UA should prefetch **image_jpeg.sxg** which +content is JPEG format. ## Security and Privacy Considerations -The UA must fetch the alternate signed exchange subresource (lib.js.sxg) even if there is the original subresource (lib.js) in the HTTPCache. Otherwise it leaks the state of publisher’s site to the distributor of the signed exchange. +The UA must fetch the alternate signed exchange subresource (lib.js.sxg) even if +there is the original subresource (lib.js) in the HTTPCache. Otherwise it leaks +the state of publisher’s site to the distributor of the signed exchange. +Also, to prevent tracking (user ID transfer), if the aggregator failed to +prefetch a subresource that the main resource preloads, the UA must drop all of +the subresource prefetches. If the aggregator prefetches a superset of the +preloaded subresources, the UA must drop the ones that weren't preloaded. ## [Self-Review Questionnaire: Security and Privacy](https://www.w3.org/TR/security-privacy-questionnaire/) -1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? +1. What information might this feature expose to Web sites or other parties, and +for what purposes is that exposure necessary? - The existence of the alternative signed exchange in HTTP Cache is exposed. -1. Is this specification exposing the minimum amount of information necessary to power the feature? +1. Is this specification exposing the minimum amount of information necessary to +power the feature? - Yes. -1. How does this specification deal with personal information or personally-identifiable information or information derived thereof? +1. How does this specification deal with personal information or +personally-identifiable information or information derived thereof? - Signed Exchange should not include personal information. 1. How does this specification deal with sensitive information? - Signed Exchange should not include sensitive information. -1. Does this specification introduce new state for an origin that persists across browsing sessions? - - No. The prefetched signed exchange is stored to HTTPCache. But this is the existing behavior when directly prefetching the signed exchange using ``. -1. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? +1. Does this specification introduce new state for an origin that persists +across browsing sessions? + - No. The prefetched signed exchange is stored to HTTPCache. But this is the + existing behavior when directly prefetching the signed exchange using + ``. +1. What information from the underlying platform, e.g. configuration data, is +exposed by this specification to an origin? - This exposes whether the UA support this feature or not. 1. Does this specification allow an origin access to sensors on a user’s device - No -1. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. +1. What data does this specification expose to an origin? Please also document +what data is identical to data exposed by other features, in the same or +different contexts. - The existence of the alternative signed exchange in HTTP Cache is exposed. - - But this is the same as the existing behavior when directly prefetching the signed exchange using ``. + - But this is the same as the existing behavior when directly prefetching the + signed exchange using ``. 1. Does this specification enable new script execution/loading mechanisms? - No 1. Does this specification allow an origin to access other devices? - No -1. Does this specification allow an origin some measure of control over a user agent’s native UI? +1. Does this specification allow an origin some measure of control over a user +agent’s native UI? - No -1. What temporary identifiers might this this specification create or expose to the web? +1. What temporary identifiers might this this specification create or expose to +the web? - No -1. How does this specification distinguish between behavior in first-party and third-party contexts? +1. How does this specification distinguish between behavior in first-party and +third-party contexts? - This feature should work well with third-party signed exchange. - - To avoid leaking the state of publisher’s site to the distributor of the signed exchange, the UA must fetch the alternate signed exchange subresource even if there is the original subresource in the HTTPCache. -1. How does this specification work in the context of a user agent’s Private \ Browsing or "incognito" mode? + - To avoid leaking the state of publisher’s site to the distributor of the + signed exchange, the UA must fetch the alternate signed exchange subresource + even if there is the original subresource in the HTTPCache. +1. How does this specification work in the context of a user agent’s Private +Browsing or "incognito" mode? - No difference while the user is browsing sites in Private mode. -1. Does this specification have a "Security Considerations" and "Privacy Considerations" section? +1. Does this specification have a "Security Considerations" and "Privacy +Considerations" section? - Yes 1. Does this specification allow downgrading default security characteristics? - No diff --git a/explainers/signed-exchange-subresource-subtitution-explainer.md b/explainers/signed-exchange-subresource-subtitution-explainer.md index c5878c55..f38eeb0d 100644 --- a/explainers/signed-exchange-subresource-subtitution-explainer.md +++ b/explainers/signed-exchange-subresource-subtitution-explainer.md @@ -2,66 +2,159 @@ ## Introduction -We want to introduce a new **rel=allowed-alt-sxg** link HTTP header which will be used along with rel=preload link HTTP header. By using this header, content publishers can declare that the UA can load the specific subresources from cached signed exchanges which were prefetched in the referrer page. +We want to introduce a new **rel=allowed-alt-sxg** link HTTP header which will +be used along with rel=preload link HTTP header. By using this header, content +publishers can declare that the UA can load the specific subresources from +cached signed exchanges which were prefetched in the referrer page. ## Use Cases ### Privacy-preserving prefetching subresources -A user is browsing a news feed site (https://feed.example/). The user clicks a link to an article in another site (https://publisher.example/article.html). The article is using a large JS library (https://cdn.publisher.example/lib.js) and the user must wait for the JS file to be fetched from the server to read the article. +A user is browsing a news feed site (https://feed.example/). The user clicks a +link to an article in another site (https://publisher.example/article.html). The +article is using a large JS library (https://cdn.publisher.example/lib.js) and +the user must wait for the JS file to be fetched from the server to read the +article. -If the feed site knows that the article is depending on the JS file, the site can insert a link element (``) to prefetch the JS file while the user is browsing the feed site. But this is problematic from the privacy point of view. And also this doesn’t work if the UA is using [origin isolated HTTPCache mechanism](http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html). +If the feed site knows that the article is depending on the JS file, the site +can insert a link element (``) to prefetch the JS +file while the user is browsing the feed site. But this is problematic from the +privacy point of view. And also this doesn’t work if the UA is using +[origin isolated HTTPCache mechanism](http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html). -Signed Exchange has solved this [privacy-preserving prefetching](https://wicg.github.io/webpackage/draft-yasskin-webpackage-use-cases.html#private-prefetch) problem for main resources. If the publisher is providing the article in signed exchange format (article.html.sxg), the UA can prefetch the signed exchange from the feed site’s own server while the user is browsing the feed site. But there is no way to prefetch subresources in a privacy-preserving manner yet. +Signed Exchange has solved this +[privacy-preserving prefetching](https://wicg.github.io/webpackage/draft-yasskin-webpackage-use-cases.html#private-prefetch) +problem for main resources. If the publisher is providing the article in signed +exchange format (article.html.sxg), the UA can prefetch the signed exchange from +the feed site’s own server while the user is browsing the feed site. But there +is no way to prefetch subresources in a privacy-preserving manner yet. Our proposal can solve this problem: -1. The publisher provides the script file in signed exchange format (lib.js.sxg) along with its [header integrity value](#header-integrity-of-signed-exchange). -1. The UA prefetches the signed exchange of the script from the feed site’s own server while the user is browsing the feed site. -1. The HTTP response of the article from the publisher's server (https://publisher.example/article.html) has an allowed-alt-sxg link header to declare that the UA can load the script from the prefetched signed exchange. +1. The publisher provides the script file in signed exchange format (lib.js.sxg) +along with its [header integrity value](#header-integrity-of-signed-exchange). +1. The UA prefetches the signed exchange of the script from the feed site’s own +server while the user is browsing the feed site. +1. The HTTP response of the article from the publisher's server (https://publisher.example/article.html) has an allowed-alt-sxg link header to declare +that the UA can load the script from the prefetched signed exchange. ``` Link: ; rel="allowed-alt-sxg"; header-integrity="sha256-..." ``` - So, the UA can load the JS file from the prefetched signed exchange. If the publisher is providing the article in signed exchange format (article.html.sxg), the allowed-alt-sxg link header is in the inner response headers of the signed exchange. + So, the UA can load the JS file from the prefetched signed exchange. If the + publisher is providing the article in signed exchange format + (article.html.sxg), the allowed-alt-sxg link header is in the inner response + headers of the signed exchange. ### Reading article while offline -If the publisher is providing the main resource and necessary subresources in signed exchange format, the user of the news feed site can read the article even while offline. This can be done using Service Worker. -1. The Service Worker of the news feed site fetches the main resource signed exchange and subresources signed exchanges (maybe using [Background Fetch](https://wicg.github.io/background-fetch/)) while online, and stores them to the CacheStorage of the feed site origin. -1. While the user is browsing the feed site, the site inserts prefetch link elements to prefetch the signed exchanges. The service worker responds to the fetch events of the prefetch with the signed exchanges in the CacheStorage. -1. When the user clicks a link to the article’s signed exchange, the content and all necessary subresources are loaded from the cached signed exchange. So the user can read the article while offline. +If the publisher is providing the main resource and necessary subresources in +signed exchange format, the user of the news feed site can read the article even +while offline. This can be done using Service Worker. +1. The Service Worker of the news feed site fetches the main resource signed +exchange and subresources signed exchanges (maybe using +[Background Fetch](https://wicg.github.io/background-fetch/)) while online, and +stores them to the CacheStorage of the feed site origin. +1. While the user is browsing the feed site, the site inserts prefetch link +elements to prefetch the signed exchanges. The service worker responds to the +fetch events of the prefetch with the signed exchanges in the CacheStorage. +1. When the user clicks a link to the article’s signed exchange, the content and +all necessary subresources are loaded from the cached signed exchange. So the +user can read the article while offline. # Proposal -1. Introduce SignedExchangeCache and PrefetchedSignedExchangeCache which are attached to a Document. SignedExchangeCache keeps the signed exchanges which are prefetched from the Document. PrefetchedSignedExchangeCache keeps the signed exchanges which were passed from the referrer Document which triggered the navigation to the current Document. -1. While processing "[prefetch](https://html.spec.whatwg.org/multipage/links.html#link-type-prefetch)" link (eg: ``): - - If succeeded prefetching the signed exchange (including merkle integrity check of the body), stores the parsedExchange which is the result of [parsing a signed exchange](https://wicg.github.io/webpackage/loading.html#ref-for-parsing-a-signed-exchange) (= inner request URL and inner response) to the SignedExchangeCache. -1. While [navigating across documents](https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigating-across-documents), copy the parsedExchanges in the SignedExchangeCache of the source document to the PrefetchedSignedExchangeCache of the target document. This is intended to provide a way to pass the cached signed exchange across origins even if the UA is using origin isolated HTTPCache mechanism. -1. While processing [preload](https://html.spec.whatwg.org/multipage/links.html#link-type-preload) link HTTP headers (eg: Link: ; rel="preload"; as="script"): - - Check whether matching "allowed-alt-sxg" link HTTP header (`Link: ;rel="allowed-alt-sxg";header-integrity="sha256-.."`) exists or not. (Note that if the allowed-alt-sxg link HTTP header has variants and variant-key attributes, the UA must execute the algorithm written in [HTTP Representation Variants spec](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) to find the matching header.) - - Check whether all preload links which have matching allowed-alt-sxg link header have matching (url and header-integrity) parsedExchange in PrefetchedSignedExchangeCache. If the check passes, set request's stashed exchange to the parsedExchange so the resource will be loaded from the cached signed exchange. - - After processing the link HTTP headers, clears the PrefetchedSignedExchangeCache. +1. Introduce SignedExchangeCache and PrefetchedSignedExchangeCache which are +attached to a Document. SignedExchangeCache keeps the signed exchanges which are +prefetched from the Document. PrefetchedSignedExchangeCache keeps the signed +exchanges which were passed from the referrer Document which triggered the +navigation to the current Document. +1. While processing +"[prefetch](https://html.spec.whatwg.org/multipage/links.html#link-type-prefetch)" +link (eg: ``): + - If succeeded prefetching the signed exchange (including merkle integrity + check of the body), stores the parsedExchange which is the result of + [parsing a signed exchange](https://wicg.github.io/webpackage/loading.html#ref-for-parsing-a-signed-exchange) + (= inner request URL and inner response) to the SignedExchangeCache. +1. While +[navigating across documents](https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigating-across-documents), +copy the parsedExchanges in the SignedExchangeCache of the source document to +the PrefetchedSignedExchangeCache of the target document. This is intended to +provide a way to pass the cached signed exchange across origins even if the UA +is using origin isolated HTTPCache mechanism. +1. While processing +[preload](https://html.spec.whatwg.org/multipage/links.html#link-type-preload) +link HTTP headers (eg: Link: ; +rel="preload"; as="script"): + - Check whether matching "allowed-alt-sxg" link HTTP header + (`Link: ;rel="allowed-alt-sxg";header-integrity="sha256-.."`) + exists or not. (Note that if the allowed-alt-sxg link HTTP header has + variants and variant-key attributes, the UA must execute the algorithm + written in + [HTTP Representation Variants spec](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) + to find the matching header.) + - Check whether all preload links which have matching allowed-alt-sxg link + header have matching (url and header-integrity) parsedExchange in + PrefetchedSignedExchangeCache. If the check passes, set request's stashed + exchange to the parsedExchange so the resource will be loaded from the cached + signed exchange. + - After processing the link HTTP headers, clears the + PrefetchedSignedExchangeCache. # Detailed design discussion ## Header integrity of signed exchange -We use the SHA256 hash value of *signedHeaders* in [application/signed-exchange format](https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange) for integrity checking. This signedHeaders is *"the canonical serialization of the CBOR representation of the response headers of the exchange represented by the application/signed-exchange resource, excluding the Signature header field"*. So this value doesn’t change even if the publisher signs the content again or changes the signing key. This header-integrity value can verify the integrity of both the response header and the content body, because signed exchange’s response header must have digest header. +We use the SHA256 hash value of *signedHeaders* in +[application/signed-exchange format](https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange) +for integrity checking. This signedHeaders is *"the canonical serialization of +the CBOR representation of the response headers of the exchange represented by +the application/signed-exchange resource, excluding the Signature header +field"*. So this value doesn’t change even if the publisher signs the content +again or changes the signing key. This header-integrity value can verify the +integrity of both the response header and the content body, because signed +exchange’s response header must have digest header. -The UA needs to check that this value of the prefetched subresource signed exchange is same as the header-integrity attribute of allowed-alt-sxg link header in the response from the publisher. This is intended to prevent the distributor from encoding a tracking ID into the subresource signed exchange. +The UA needs to check that this value of the prefetched subresource signed +exchange is same as the header-integrity attribute of allowed-alt-sxg link +header in the response from the publisher. This is intended to prevent the +distributor from encoding a tracking ID into the subresource signed exchange. -We can’t use the [SRI’s integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) for this purpose, because SRI’s integrity can be used only for verifying the integrity of the content body. So if the UA use the SRI’s integrity value in allowed-alt-sxg link header, we can use the subresource signed exchanges to track the users by changing content-type and detecting the image loading failure. +We can’t use the +[SRI’s integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) +for this purpose, because SRI’s integrity can be used only for verifying the +integrity of the content body. So if the UA use the SRI’s integrity value in +allowed-alt-sxg link header, we can use the subresource signed exchanges to +track the users by changing content-type and detecting the image loading +failure. ## Multiple subresource signed exchanges -If there are multiple matching subresource signed exchanges (example: script.js.sxg and image.jpg.sxg), the UA must check that there is no error in the all signed exchanges (eg: sig matching, URL matching, Merkle Integrity error) before processing the content of the signed exchanges. This is intended to prevent the distributor from encoding a tracking ID into the set of subresources it prefetches. this means that the UA can use the subresource signed exchanges only when they are defined in the header. +If there are multiple matching subresource signed exchanges (example: +script.js.sxg and image.jpg.sxg), the UA must check that there is no error in +the all signed exchanges (eg: sig matching, URL matching, Merkle Integrity +error) before processing the content of the signed exchanges. This is intended +to prevent the distributor from encoding a tracking ID into the set of +subresources it prefetches. this means that the UA can use the subresource +signed exchanges only when they are defined in the header. ## Can’t we have a global SignedExchangeCache? -If we can have a global SignedExchangeCache, we can use the all signed exchanges which have previously prefetched, even if they are not prefetched by the referrer page. This can -improve the performance. But this introduces privacy issues such as [Timing Leaks](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#cache_timing) and [Deterministic History Leaks](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#history_leaks) described in [the document about Subresource Integrity Addressable Caching](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html). +If we can have a global SignedExchangeCache, we can use the all signed exchanges +which have previously prefetched, even if they are not prefetched by the +referrer page. This can improve the performance. But this introduces privacy +issues such as +[Timing Leaks](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#cache_timing) +and [Deterministic History Leaks](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#history_leaks) +described in [the document about Subresource Integrity Addressable Caching](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html). -To avoid these privacy issues, we introduced the limitation that we can only use the signed exchanges which were prefetched by the referrer page. +To avoid these privacy issues, we introduced the limitation that we can only use +the signed exchanges which were prefetched by the referrer page. ## Can’t we merge allowed-alt-sxg to preload header? -If we can declare the header-integrity value in the existing preload link HTTP header, we don’t need to introduce a new "allowed-alt-sxg" link HTTP header. But it becomes complicated when supporting the [imagesrcset attribute of preload link](https://github.com/w3c/preload/issues/120). +If we can declare the header-integrity value in the existing preload link HTTP +header, we don’t need to introduce a new "allowed-alt-sxg" link HTTP header. But +it becomes complicated when supporting the +[imagesrcset attribute of preload link](https://github.com/w3c/preload/issues/120). For Example: ``` @@ -72,7 +165,9 @@ Link: ; https://publisher.example/narrow.jpg 320w"; imagesizes="(max-width: 640px) 100vw, 640px" ``` -In this case, we want to declare that both wide.jpg and narrow.jpg can be loaded from signed exchanges and the header-integrity is sha256-XXX and sha256-YYY. But how to express in this preload link header? +In this case, we want to declare that both wide.jpg and narrow.jpg can be loaded +from signed exchanges and the header-integrity is sha256-XXX and sha256-YYY. But +how to express in this preload link header? In our proposal, we can have two allowed-alt-sxg link headers. ``` @@ -85,10 +180,16 @@ Link: ; ``` ## Lifetime of the entry in SignedExchangeCache -The UA must check both the [signature expire time](https://wicg.github.io/webpackage/loading.html#exchange-signature-expiration-time) of the signed exchange and Cache-Control header of the outer response. The UA may discard the entry if it is expired. +The UA must check both the +[signature expire time](https://wicg.github.io/webpackage/loading.html#exchange-signature-expiration-time) +of the signed exchange and Cache-Control header of the outer response. The UA +may discard the entry if it is expired. ## Content negotiation using Variants and Variant-Key -The **allowed-alt-sxg** link headers can have [variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) attributes to support content negotiation (eg: [WebP support](https://developers.google.com/speed/webp/faq#server-side_content_negotiation_via_accept_headers)). +The **allowed-alt-sxg** link headers can have +[variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) +attributes to support content negotiation (eg: +[WebP support](https://developers.google.com/speed/webp/faq#server-side_content_negotiation_via_accept_headers)). ``` Link: ; rel="allowed-alt-sxg"; @@ -102,53 +203,112 @@ Link: ; header-integrity="sha256-BBB" Link: ; rel=preload; as=image; ``` -If a UA supports WebP format, the UA can use the signed exchange which header-integrity is sha256-BBB if available in the cache. Otherwise the UA can use the signed exchange which header-integrity is sha256-AAA if available in the cache. +If a UA supports WebP format, the UA can use the signed exchange which +header-integrity is sha256-BBB if available in the cache. Otherwise the UA can +use the signed exchange which header-integrity is sha256-AAA if available in the +cache. -If the sha256-AAA signed exchange exists in the cache but the sha256-BBB signed exchange doesn’t exists, the UA which supports WebP format MUST ignore the sha256-AAA signed exchange and fetch the original URL. Otherwise this can be used for sending tracking ID. +If the sha256-AAA signed exchange exists in the cache but the sha256-BBB signed +exchange doesn’t exists, the UA which supports WebP format MUST ignore the +sha256-AAA signed exchange and fetch the original URL. Otherwise this can be +used for sending tracking ID. ## Security and Privacy Considerations -- The publishers can know whether the referrer page has prefetched the signed exchange subresources or not by checking the resource timing information. But this only exposes 1 bit information (= yes or no) because UAs can use the cached signed exchange only if the required signed exchanges are all available. -- The UA can use the prefetched signed exchange subresources, only when they were prefetched in the referrer page. This is intended to avoid leaking the prefetching state to succeeding pages. -- The UA check the header integrity value, so the distributor of the subresource signed exchange can’t inject arbitrary resources to the publisher’s page. This prevents distributors from sending tracking IDs to the publisher’s page. -- The UA need to check both [the request URL](https://wicg.github.io/webpackage/loading.html#exchange-request-url) and the header integrity value of the signed exchange to avoid [Origin Laundering](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#origin_laundering) attack. The URL is not in signedHeaders, so the header integrity value can’t check the URL is correct. -- The UA must fetch the signed exchange subresource (https://cdn.feed.example/cdn.publisher.example/lib.js.sxg) while processing the prefetch link element (``) even if there is the original subresource (http://cdn.publisher.example/lib.js) in the HTTPCache. Otherwise it leaks the state of publisher’s site to the distributor of the signed exchange. -- The UA must ignore the not-yet-completed subresource signed exchange prefetch to prevent distributors from interfering the publisher’s page. (Eg. Intentionally block or delay the subresource loading.) So if the user clicks the link to the article while the UA is still prefetching the subresource signed exchange, the UA must fetch the subresource from the original URL after navigation. -- The UA can use the prefetched signed exchange subresources only if the preload HTTP link headers for the subresources exist in the response headers. It is because the UA need to check the availability of all required signed exchanges before start loading subresources. +- The publishers can know whether the referrer page has prefetched the signed +exchange subresources or not by checking the resource timing information. But +this only exposes 1 bit information (= yes or no) because UAs can use the cached +signed exchange only if the required signed exchanges are all available. +- The UA can use the prefetched signed exchange subresources, only when they +were prefetched in the referrer page. This is intended to avoid leaking the +prefetching state to succeeding pages. +- The UA check the header integrity value, so the distributor of the subresource +signed exchange can’t inject arbitrary resources to the publisher’s page. This +prevents distributors from sending tracking IDs to the publisher’s page. +- The UA need to check both +[the request URL](https://wicg.github.io/webpackage/loading.html#exchange-request-url) +and the header integrity value of the signed exchange to avoid +[Origin Laundering](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#origin_laundering) +attack. The URL is not in signedHeaders, so the header integrity value can’t +check the URL is correct. +- The UA must fetch the signed exchange subresource +(https://cdn.feed.example/cdn.publisher.example/lib.js.sxg) while processing the +prefetch link element (``) +even if there is the original subresource (http://cdn.publisher.example/lib.js) +in the HTTPCache. Otherwise it leaks the state of publisher’s site to the +distributor of the signed exchange. +- The UA must ignore the not-yet-completed subresource signed exchange prefetch +to prevent distributors from interfering the publisher’s page. (Eg. +Intentionally block or delay the subresource loading.) So if the user clicks the +link to the article while the UA is still prefetching the subresource signed +exchange, the UA must fetch the subresource from the original URL after +navigation. +- The UA can use the prefetched signed exchange subresources only if the preload +HTTP link headers for the subresources exist in the response headers. It is +because the UA need to check the availability of all required signed exchanges +before start loading subresources. ## [Self-Review Questionnaire: Security and Privacy](https://www.w3.org/TR/security-privacy-questionnaire/) -1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? - - This feature exposes the 1 bit information "the referrer page has prefetched the signed exchange subresources or not" to the publisher. -1. Is this specification exposing the minimum amount of information necessary to power the feature? - - Yes. This proposal has limitations such as "all subresource SXG must be finished prefetching, otherwise ignored", "subresource SXG must be prefetched even if the original subresource exists in HTTPCache". -1. How does this specification deal with personal information or personally-identifiable information or information derived thereof? +1. What information might this feature expose to Web sites or other parties, and +for what purposes is that exposure necessary? + - This feature exposes the 1 bit information "the referrer page has + prefetched the signed exchange subresources or not" to the publisher. +1. Is this specification exposing the minimum amount of information necessary to +power the feature? + - Yes. This proposal has limitations such as "all subresource SXG must be + finished prefetching, otherwise ignored", "subresource SXG must be prefetched + even if the original subresource exists in HTTPCache". +1. How does this specification deal with personal information or +personally-identifiable information or information derived thereof? - Signed Exchange should not include personal information. 1. How does this specification deal with sensitive information? - Signed Exchange should not include sensitive information. -1. Does this specification introduce new state for an origin that persists across browsing sessions? - - No. The prefetched signed exchange subresources can be used only from the pages which are navigated from the document which prefetched them. -1. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? +1. Does this specification introduce new state for an origin that persists +across browsing sessions? + - No. The prefetched signed exchange subresources can be used only from the + pages which are navigated from the document which prefetched them. +1. What information from the underlying platform, e.g. configuration data, is +exposed by this specification to an origin? - This exposes whether the UA support this feature or not. 1. Does this specification allow an origin access to sensors on a user’s device - No -1. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. - - This feature exposes the 1 bit information "the referrer page has prefetched the signed exchange subresources or not" to the publisher. - - Sending 1 bit information from the distributor to the publisher is already easily possible just by changing the URL. +1. What data does this specification expose to an origin? Please also document +what data is identical to data exposed by other features, in the same or +different contexts. + - This feature exposes the 1 bit information "the referrer page has + prefetched the signed exchange subresources or not" to the publisher. + - Sending 1 bit information from the distributor to the publisher is already + easily possible just by changing the URL. 1. Does this specification enable new script execution/loading mechanisms? - - This specification introduces a new script loading path, from prefetched signed exchange. The existing security checks such as CSP/CORP must be applied as if the script is loaded from the original URL. + - This specification introduces a new script loading path, from prefetched + signed exchange. The existing security checks such as CSP/CORP must be + applied as if the script is loaded from the original URL. 1. Does this specification allow an origin to access other devices? - No -1. Does this specification allow an origin some measure of control over a user agent’s native UI? +1. Does this specification allow an origin some measure of control over a user +agent’s native UI? - No -1. What temporary identifiers might this this specification create or expose to the web? +1. What temporary identifiers might this this specification create or expose to +the web? - No -1. How does this specification distinguish between behavior in first-party and third-party contexts? - - This feature treats all entities (the distributor of signed exchange, the publisher site, the origin of subresource URL) as third-party origins. - - To avoid leaking user-specific data in the distributor of signed exchange, the prefetch request must not contain credentials. This is covered by the "Prefetch and double-key caching" issue. - - The origin of subresource URL could be different from the origin of publisher site. The cross origin security checks (CORS/CORB/CORP/..) must be executed while reading the response from the cached signed exchanges. -1. How does this specification work in the context of a user agent’s Private \ Browsing or "incognito" mode? +1. How does this specification distinguish between behavior in first-party and +third-party contexts? + - This feature treats all entities (the distributor of signed exchange, the + publisher site, the origin of subresource URL) as third-party origins. + - To avoid leaking user-specific data in the distributor of signed exchange, + the prefetch request must not contain credentials. This is covered by the + "Prefetch and double-key caching" issue. + - The origin of subresource URL could be different from the origin of + publisher site. The cross origin security checks (CORS/CORB/CORP/..) must be + executed while reading the response from the cached signed exchanges. +1. How does this specification work in the context of a user agent’s Private +Browsing or "incognito" mode? - No difference while the user is browsing sites in Private mode. - - If the user opens a link in private mode while browsing in normal mode (eg: "Open link in incognito window"), the prefetched signed exchanges must be ignored. -1. Does this specification have a "Security Considerations" and "Privacy Considerations" section? + - If the user opens a link in private mode while browsing in normal mode (eg: + "Open link in incognito window"), the prefetched signed exchanges must be + ignored. +1. Does this specification have a "Security Considerations" and "Privacy +Considerations" section? - Yes 1. Does this specification allow downgrading default security characteristics? - No From 32b9a33dee79de969a7c8ffaad4fdc923846b5ed Mon Sep 17 00:00:00 2001 From: Tsuyoshi Horo Date: Mon, 9 Dec 2019 17:15:48 +0900 Subject: [PATCH 3/6] Incorporated jyasskin's comment --- ...igned-exchange-alternate-link-explainer.md | 63 ++++++------ ...hange-subresource-subtitution-explainer.md | 96 +++++++++---------- 2 files changed, 81 insertions(+), 78 deletions(-) diff --git a/explainers/signed-exchange-alternate-link-explainer.md b/explainers/signed-exchange-alternate-link-explainer.md index 084c2b6e..88d06de1 100644 --- a/explainers/signed-exchange-alternate-link-explainer.md +++ b/explainers/signed-exchange-alternate-link-explainer.md @@ -2,23 +2,22 @@ ## Introduction We want to allow the publisher of a resource to declare that a signed exchange is available holding the content of either that resource or one of its -subresources. We expect aggregator sites (social networks, News site, search -engine..) to use this to cache the signed version of a resource in order to +subresources. We expect aggregator sites (social networks, news sites, search +engines, etc.) to use this to cache the signed version of a resource in order to serve it to their users. We expect UAs to use this to allow users to save the -page in signed exchange format. When the publisher identifies a same-origin -signed exchange for a cross-origin subresource, the UA can use that information -to recursively prefetch the subresource without exposing its speculative -activity across origins. +page in signed exchange format so they can share it with their peers. When the +publisher identifies a same-origin signed exchange for a cross-origin +subresource, the UA can use that information to recursively prefetch the +subresource without exposing its speculative activity across origins. [``](https://html.spec.whatwg.org/multipage/links.html#rel-alternate) and the equivalent `Link` header are already defined to declare that the referenced document is a reformulation of the current document as a signed exchange. To offer signed exchanges for subresources, we propose to use the [`anchor` parameter](https://tools.ietf.org/html/rfc8288#section-3.2) to -identify the replaced subresource. This may be the first use of the `anchor` +identify the replaceable subresource. This may be the first use of the `anchor` parameter in the web platform. - ## Use Cases ### Recursive subresource signed exchange prefetch While a user is browsing an aggregator site (https://feed.example), the @@ -31,10 +30,8 @@ to a signed exchange version of that article. When the UA prefetches the signed exchange (article.html.sxg), the aggregator server includes a declaration that one of `article.html`'s subresources (https://cdn.publisher.example/lib.js) is also available from the same -aggregator. - -The response from the server has an alternate link of subresource signed -exchange: +aggregator. The aggregator server expresses this by serving `article.html.sxg` +with a `Link` header identifying the subresource's alternate form: ``` Link: ; @@ -70,17 +67,19 @@ article and the script subresource are loaded from the prefetched signed exchanges. ## Proposal -While prefetching a HTML resource in signed exchange format: +While prefetching an HTML resource in signed exchange format: -1. Whent the UA detects a "preload" link HTTP header in the inner response, -check whether matching “allowed-alt-sxg” link HTTP header in the inner response -exists or not. (Note that if the allowed-alt-sxg link HTTP header has variants -and variant-key attributes, the UA must execute the algorithm written in +1. When the UA detects a "preload" link HTTP header in the inner response, check +whether a matching “allowed-alt-sxg” link HTTP header in the inner response +exists or not. (Note that multiple `allowed-alt-sxg` links can be present for +the same preload if they include `variants` and `variant-key` attributes. In +that case, the UA uses the algorithm written in [HTTP Representation Variants](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) spec to find the matching header.) -1. If exists, check whether matching “alternate” link HTTP header in the outer -response exists or not. -1. If exists, prefetches the matching signed exchange instead of prefetching the +1. If an `allowed-alt-sxg` link exists, check whether the signed exchange was +served with a matching “alternate” link HTTP header. +1. If the outer signed exchange did identify an alternate version of the +subresource, prefetch the subresource signed exchange instead of prefetching the original resource URL. 1. The prefetched signed exchange will be stored to the SignedExchangeCache of the Document. And it will be passed to the next Document and used while @@ -147,14 +146,21 @@ personally-identifiable information or information derived thereof? - Signed Exchange should not include personal information. 1. How does this specification deal with sensitive information? - Signed Exchange should not include sensitive information. + - The state of the cache for another origin is potentially sensitive, and + this specification avoids exposing it by making the decision to fetch an + alternative not depend on the presence or absence of the subresource in its + cache. 1. Does this specification introduce new state for an origin that persists across browsing sessions? - - No. The prefetched signed exchange is stored to HTTPCache. But this is the - existing behavior when directly prefetching the signed exchange using - ``. + - Prefetched resources, including signed exchanges, are stored to the HTTP + cache as normal, but the association of a signed exchange with its contained + resource is not persisted. Right now, the contained resource is not + independently stored in the HTTP cache, although that decision may be + revisited. 1. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? - - This exposes whether the UA support this feature or not. + - The use of Variants exposes the UA's content negotiation preferences to the + aggregator's origin, but that's already exposed by the UA's Accept headers. 1. Does this specification allow an origin access to sensors on a user’s device - No 1. What data does this specification expose to an origin? Please also document @@ -164,7 +170,8 @@ different contexts. - But this is the same as the existing behavior when directly prefetching the signed exchange using ``. 1. Does this specification enable new script execution/loading mechanisms? - - No + - Loading a script from a signed exchange is different from loading it over + TLS. We think it's not significantly different. 1. Does this specification allow an origin to access other devices? - No 1. Does this specification allow an origin some measure of control over a user @@ -172,7 +179,7 @@ agent’s native UI? - No 1. What temporary identifiers might this this specification create or expose to the web? - - No + - None 1. How does this specification distinguish between behavior in first-party and third-party contexts? - This feature should work well with third-party signed exchange. @@ -186,4 +193,6 @@ Browsing or "incognito" mode? Considerations" section? - Yes 1. Does this specification allow downgrading default security characteristics? - - No + - There's active discussion about how signed exchanges are a downgrade + compared to TLS, and this particular specification allows recursive use of + signed exchanges. diff --git a/explainers/signed-exchange-subresource-subtitution-explainer.md b/explainers/signed-exchange-subresource-subtitution-explainer.md index f38eeb0d..3d7f5549 100644 --- a/explainers/signed-exchange-subresource-subtitution-explainer.md +++ b/explainers/signed-exchange-subresource-subtitution-explainer.md @@ -2,10 +2,9 @@ ## Introduction -We want to introduce a new **rel=allowed-alt-sxg** link HTTP header which will -be used along with rel=preload link HTTP header. By using this header, content -publishers can declare that the UA can load the specific subresources from -cached signed exchanges which were prefetched in the referrer page. +We want to allow content publishers to declare that the UA can load the specific +subresources from cached signed exchanges which were prefetched in the referrer +page. So we propose a new **rel=allowed-alt-sxg** link HTTP header. ## Use Cases @@ -20,55 +19,47 @@ article. If the feed site knows that the article is depending on the JS file, the site can insert a link element (``) to prefetch the JS -file while the user is browsing the feed site. But this is problematic from the -privacy point of view. And also this doesn’t work if the UA is using -[origin isolated HTTPCache mechanism](http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html). +file while the user is browsing the feed site. But this leaks that the user's +feed pages include a page using this JS library before the user has +consented by clicking on the link. -Signed Exchange has solved this -[privacy-preserving prefetching](https://wicg.github.io/webpackage/draft-yasskin-webpackage-use-cases.html#private-prefetch) -problem for main resources. If the publisher is providing the article in signed -exchange format (article.html.sxg), the UA can prefetch the signed exchange from -the feed site’s own server while the user is browsing the feed site. But there -is no way to prefetch subresources in a privacy-preserving manner yet. +There is an ongoing +[spec discussion](https://github.com/w3c/resource-hints/issues/82) to make +cross-origin navigation prefetch work with double key caching which is proposed +to protect against +[HTTP Cache Cross-Site Leaks](http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html). But as long as the UA needs to fetch the +resource from the publisher's server, this +[privacy leak problem](https://wicg.github.io/webpackage/draft-yasskin-wpack-use-cases.html#private-prefetch) + can't be solved. -Our proposal can solve this problem: -1. The publisher provides the script file in signed exchange format (lib.js.sxg) -along with its [header integrity value](#header-integrity-of-signed-exchange). +Signed Exchange solve this privacy-preserving prefetching problem for main +resources. If the publisher is providing the article in signed exchange format +(article.html.sxg), the UA can prefetch the signed exchange from the feed site’s +own server while the user is browsing the feed site. But there is no way to +prefetch subresources in a privacy-preserving manner yet. + +Our proposal can solve this problem for subresources: +1. The publisher provides the script file in signed exchange format +(lib.js.sxg). 1. The UA prefetches the signed exchange of the script from the feed site’s own server while the user is browsing the feed site. -1. The HTTP response of the article from the publisher's server (https://publisher.example/article.html) has an allowed-alt-sxg link header to declare -that the UA can load the script from the prefetched signed exchange. +1. The HTTP response of the article from the publisher's server +(https://publisher.example/article.html) has an `allowed-alt-sxg` link header to +declare exactly what version of the subresource is compatible with this main +resource. ``` Link: ; rel="allowed-alt-sxg"; header-integrity="sha256-..." ``` - So, the UA can load the JS file from the prefetched signed exchange. If the - publisher is providing the article in signed exchange format - (article.html.sxg), the allowed-alt-sxg link header is in the inner response - headers of the signed exchange. - -### Reading article while offline -If the publisher is providing the main resource and necessary subresources in -signed exchange format, the user of the news feed site can read the article even -while offline. This can be done using Service Worker. -1. The Service Worker of the news feed site fetches the main resource signed -exchange and subresources signed exchanges (maybe using -[Background Fetch](https://wicg.github.io/background-fetch/)) while online, and -stores them to the CacheStorage of the feed site origin. -1. While the user is browsing the feed site, the site inserts prefetch link -elements to prefetch the signed exchanges. The service worker responds to the -fetch events of the prefetch with the signed exchanges in the CacheStorage. -1. When the user clicks a link to the article’s signed exchange, the content and -all necessary subresources are loaded from the cached signed exchange. So the -user can read the article while offline. - # Proposal -1. Introduce SignedExchangeCache and PrefetchedSignedExchangeCache which are -attached to a Document. SignedExchangeCache keeps the signed exchanges which are -prefetched from the Document. PrefetchedSignedExchangeCache keeps the signed +1. Introduce two new cache mechanism SignedExchangeCache and +PrefetchedSignedExchangeCache in a Document. + - SignedExchangeCache keeps the signed exchanges which are +prefetched from the Document. + - PrefetchedSignedExchangeCache keeps the signed exchanges which were passed from the referrer Document which triggered the navigation to the current Document. 1. While processing @@ -106,15 +97,16 @@ rel="preload"; as="script"): # Detailed design discussion ## Header integrity of signed exchange -We use the SHA256 hash value of *signedHeaders* in +The `header-integrity` parameter of the `allowed-alt-sxg` link is the SHA256 +hash value of the *signedHeaders* value from the [application/signed-exchange format](https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange) for integrity checking. This signedHeaders is *"the canonical serialization of the CBOR representation of the response headers of the exchange represented by the application/signed-exchange resource, excluding the Signature header field"*. So this value doesn’t change even if the publisher signs the content -again or changes the signing key. This header-integrity value can verify the -integrity of both the response header and the content body, because signed -exchange’s response header must have digest header. +again or changes the signing key. This header-integrity value also guarantees +the content body hasn't changed, because the signed headers are required to +include a `Digest` header with a hash of the content body. The UA needs to check that this value of the prefetched subresource signed exchange is same as the header-integrity attribute of allowed-alt-sxg link @@ -123,8 +115,8 @@ distributor from encoding a tracking ID into the subresource signed exchange. We can’t use the [SRI’s integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) -for this purpose, because SRI’s integrity can be used only for verifying the -integrity of the content body. So if the UA use the SRI’s integrity value in +for this purpose, because SRI’s integrity only covers the content body and not +any of the headers. So if the UA use the SRI’s integrity value in allowed-alt-sxg link header, we can use the subresource signed exchanges to track the users by changing content-type and detecting the image loading failure. @@ -133,10 +125,12 @@ failure. If there are multiple matching subresource signed exchanges (example: script.js.sxg and image.jpg.sxg), the UA must check that there is no error in the all signed exchanges (eg: sig matching, URL matching, Merkle Integrity -error) before processing the content of the signed exchanges. This is intended -to prevent the distributor from encoding a tracking ID into the set of -subresources it prefetches. this means that the UA can use the subresource -signed exchanges only when they are defined in the header. +error) before processing the content of the signed exchanges. This means that +the UA can use the subresource signed exchanges only when they are defined in +the header. This is intended to prevent the distributor from encoding a tracking +ID into the set of subresources it prefetches. And to prevent the distributor +from selecting a version of the subresource that isn't compatible with the +selected version of the main resource, which might introduce a security hole. ## Can’t we have a global SignedExchangeCache? If we can have a global SignedExchangeCache, we can use the all signed exchanges From 02ab3eb3e9239806383e540367431e217282fb00 Mon Sep 17 00:00:00 2001 From: Tsuyoshi Horo Date: Mon, 9 Dec 2019 18:32:49 +0900 Subject: [PATCH 4/6] merge to one explainer --- ...igned-exchange-alternate-link-explainer.md | 198 ------------------ ...hange-subresource-subtitution-explainer.md | 176 ++++++++++++++-- 2 files changed, 161 insertions(+), 213 deletions(-) delete mode 100644 explainers/signed-exchange-alternate-link-explainer.md diff --git a/explainers/signed-exchange-alternate-link-explainer.md b/explainers/signed-exchange-alternate-link-explainer.md deleted file mode 100644 index 88d06de1..00000000 --- a/explainers/signed-exchange-alternate-link-explainer.md +++ /dev/null @@ -1,198 +0,0 @@ -# Signed Exchange alternate link -## Introduction -We want to allow the publisher of a resource to declare that a signed exchange -is available holding the content of either that resource or one of its -subresources. We expect aggregator sites (social networks, news sites, search -engines, etc.) to use this to cache the signed version of a resource in order to -serve it to their users. We expect UAs to use this to allow users to save the -page in signed exchange format so they can share it with their peers. When the -publisher identifies a same-origin signed exchange for a cross-origin -subresource, the UA can use that information to recursively prefetch the -subresource without exposing its speculative activity across origins. - -[``](https://html.spec.whatwg.org/multipage/links.html#rel-alternate) -and the equivalent `Link` header are already defined to declare that the -referenced document is a reformulation of the current document as a signed -exchange. To offer signed exchanges for subresources, we propose to use the -[`anchor` parameter](https://tools.ietf.org/html/rfc8288#section-3.2) to -identify the replaceable subresource. This may be the first use of the `anchor` -parameter in the web platform. - -## Use Cases -### Recursive subresource signed exchange prefetch -While a user is browsing an aggregator site (https://feed.example), the -aggregator guesses that the user is likely to want to read a particular article -(https://publisher.example/article.html) and so inserts a prefetch link pointing -to a signed exchange version of that article. - ``` - - ``` -When the UA prefetches the signed exchange (article.html.sxg), the aggregator -server includes a declaration that one of `article.html`'s subresources -(https://cdn.publisher.example/lib.js) is also available from the same -aggregator. The aggregator server expresses this by serving `article.html.sxg` -with a `Link` header identifying the subresource's alternate form: - -``` -Link: ; - rel="alternate"; - type="application/signed-exchange;v=b3"; - anchor="https://cdn.publisher.example/lib.js" -``` - -To prevent an attacker from loading an incompatible version of the subresource, -the resource _inside_ the signed exchange has to identify the exact version of -the replacement signed exchange using a `Link: ... rel="allowed-alt-sxg"` with -the hash of the signed headers (which themselves include a hash of the content). - -To prevent a tracker from conveying a user ID in their choice of which -subresources to prefetch, the inner resource has to preload the same -subresources that the aggregator prefetches. -And the inner response of the main resource signed exchange (article.html.sxg) -has a preload header and an allowed-alt-sxg header: - -``` -Link: ; - rel="preload"; - as="script" -Link: ; - rel="allowed-alt-sxg"; - header-integrity="sha256-XXXXXX" -``` - -The UA recursively prefetches lib.js.sxg. - -If the user navigates to the expected article, both the main resource of the -article and the script subresource are loaded from the prefetched signed -exchanges. - -## Proposal -While prefetching an HTML resource in signed exchange format: - -1. When the UA detects a "preload" link HTTP header in the inner response, check -whether a matching “allowed-alt-sxg” link HTTP header in the inner response -exists or not. (Note that multiple `allowed-alt-sxg` links can be present for -the same preload if they include `variants` and `variant-key` attributes. In -that case, the UA uses the algorithm written in -[HTTP Representation Variants](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) -spec to find the matching header.) -1. If an `allowed-alt-sxg` link exists, check whether the signed exchange was -served with a matching “alternate” link HTTP header. -1. If the outer signed exchange did identify an alternate version of the -subresource, prefetch the subresource signed exchange instead of prefetching the -original resource URL. -1. The prefetched signed exchange will be stored to the SignedExchangeCache of -the Document. And it will be passed to the next Document and used while -processing the preload link header. This behavior is written in -[Signed Exchange subresource substitution explainer](./signed-exchange-subresource-subtitution-explainer.md). - -## Content negotiation using Variants and Variant-Key -The **alternate** link header and **allowed-alt-sxg** link headers can have -[variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) -attributes to support content negotiation (eg: -[WebP support](https://developers.google.com/speed/webp/faq#server-side_content_negotiation_via_accept_headers)). - -- In **outer** HTTP response of article.html.sxg from feed.example: - ``` - Link: ; - rel="alternate"; - type="application/signed-exchange;v=b3"; - variants-05="accept;image/jpeg;image/webp"; - variant-key-05="image/jpeg"; - anchor="https://publisher.example/image"; - Link: ; - rel="alternate"; - type="application/signed-exchange;v=b3"; - variants-05="accept;image/jpeg;image/webp"; - variant-key-05="image/webp"; - anchor="https://publisher.example/image"; - ``` -- In **inner** response header of article.html.sxg: - ``` - Link: ; - rel="allowed-alt-sxg"; - variants-05="accept;image/jpeg;image/webp"; - variant-key-05="image/jpeg"; - header-integrity="sha256-AAA" - Link: ; - rel="allowed-alt-sxg"; - variants-05="accept;image/jpeg;image/webp"; - variant-key-05="image/webp"; - header-integrity="sha256-BBB" - Link: ; rel=preload; as=image; - ``` -If a UA supports WebP, the UA should prefetch **image_webp.sxg** which content -is WebP format. Otherwise the UA should prefetch **image_jpeg.sxg** which -content is JPEG format. - -## Security and Privacy Considerations -The UA must fetch the alternate signed exchange subresource (lib.js.sxg) even if -there is the original subresource (lib.js) in the HTTPCache. Otherwise it leaks -the state of publisher’s site to the distributor of the signed exchange. -Also, to prevent tracking (user ID transfer), if the aggregator failed to -prefetch a subresource that the main resource preloads, the UA must drop all of -the subresource prefetches. If the aggregator prefetches a superset of the -preloaded subresources, the UA must drop the ones that weren't preloaded. - -## [Self-Review Questionnaire: Security and Privacy](https://www.w3.org/TR/security-privacy-questionnaire/) -1. What information might this feature expose to Web sites or other parties, and -for what purposes is that exposure necessary? - - The existence of the alternative signed exchange in HTTP Cache is exposed. -1. Is this specification exposing the minimum amount of information necessary to -power the feature? - - Yes. -1. How does this specification deal with personal information or -personally-identifiable information or information derived thereof? - - Signed Exchange should not include personal information. -1. How does this specification deal with sensitive information? - - Signed Exchange should not include sensitive information. - - The state of the cache for another origin is potentially sensitive, and - this specification avoids exposing it by making the decision to fetch an - alternative not depend on the presence or absence of the subresource in its - cache. -1. Does this specification introduce new state for an origin that persists -across browsing sessions? - - Prefetched resources, including signed exchanges, are stored to the HTTP - cache as normal, but the association of a signed exchange with its contained - resource is not persisted. Right now, the contained resource is not - independently stored in the HTTP cache, although that decision may be - revisited. -1. What information from the underlying platform, e.g. configuration data, is -exposed by this specification to an origin? - - The use of Variants exposes the UA's content negotiation preferences to the - aggregator's origin, but that's already exposed by the UA's Accept headers. -1. Does this specification allow an origin access to sensors on a user’s device - - No -1. What data does this specification expose to an origin? Please also document -what data is identical to data exposed by other features, in the same or -different contexts. - - The existence of the alternative signed exchange in HTTP Cache is exposed. - - But this is the same as the existing behavior when directly prefetching the - signed exchange using ``. -1. Does this specification enable new script execution/loading mechanisms? - - Loading a script from a signed exchange is different from loading it over - TLS. We think it's not significantly different. -1. Does this specification allow an origin to access other devices? - - No -1. Does this specification allow an origin some measure of control over a user -agent’s native UI? - - No -1. What temporary identifiers might this this specification create or expose to -the web? - - None -1. How does this specification distinguish between behavior in first-party and -third-party contexts? - - This feature should work well with third-party signed exchange. - - To avoid leaking the state of publisher’s site to the distributor of the - signed exchange, the UA must fetch the alternate signed exchange subresource - even if there is the original subresource in the HTTPCache. -1. How does this specification work in the context of a user agent’s Private -Browsing or "incognito" mode? - - No difference while the user is browsing sites in Private mode. -1. Does this specification have a "Security Considerations" and "Privacy -Considerations" section? - - Yes -1. Does this specification allow downgrading default security characteristics? - - There's active discussion about how signed exchanges are a downgrade - compared to TLS, and this particular specification allows recursive use of - signed exchanges. diff --git a/explainers/signed-exchange-subresource-subtitution-explainer.md b/explainers/signed-exchange-subresource-subtitution-explainer.md index 3d7f5549..fb9b5566 100644 --- a/explainers/signed-exchange-subresource-subtitution-explainer.md +++ b/explainers/signed-exchange-subresource-subtitution-explainer.md @@ -6,6 +6,24 @@ We want to allow content publishers to declare that the UA can load the specific subresources from cached signed exchanges which were prefetched in the referrer page. So we propose a new **rel=allowed-alt-sxg** link HTTP header. +And also we want to allow the publisher of a resource to declare that a signed +exchange is available holding the content of either that resource or one of its +subresources. We expect aggregator sites (social networks, news sites, search +engines, etc.) to use this to cache the signed version of a resource in order to +serve it to their users. When the +publisher identifies a same-origin signed exchange for a cross-origin +subresource, the UA can use that information to recursively prefetch the +subresource without exposing its speculative activity across origins. + +[``](https://html.spec.whatwg.org/multipage/links.html#rel-alternate) +and the equivalent `Link` header are already defined to declare that the +referenced document is a reformulation of the current document as a signed +exchange. To offer signed exchanges for subresources, we propose to use the +[`anchor` parameter](https://tools.ietf.org/html/rfc8288#section-3.2) to +identify the replaceable subresource. This may be the first use of the `anchor` +parameter in the web platform. + + ## Use Cases ### Privacy-preserving prefetching subresources @@ -53,8 +71,59 @@ resource. header-integrity="sha256-..." ``` + +### Recursive subresource signed exchange prefetch + +While a user is browsing an aggregator site (https://feed.example), the +aggregator guesses that the user is likely to want to read a particular article +(https://publisher.example/article.html) and so inserts a prefetch link pointing +to a signed exchange version of that article. + ``` + + ``` +When the UA prefetches the signed exchange (article.html.sxg), the aggregator +server includes a declaration that one of `article.html`'s subresources +(https://cdn.publisher.example/lib.js) is also available from the same +aggregator. The aggregator server expresses this by serving `article.html.sxg` +with a `Link` header identifying the subresource's alternate form: + +``` +Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + anchor="https://cdn.publisher.example/lib.js" +``` + +To prevent an attacker from loading an incompatible version of the subresource, +the resource _inside_ the signed exchange has to identify the exact version of +the replacement signed exchange using a `Link: ... rel="allowed-alt-sxg"` with +the hash of the signed headers (which themselves include a hash of the content). + +To prevent a tracker from conveying a user ID in their choice of which +subresources to prefetch, the inner resource has to preload the same +subresources that the aggregator prefetches. +And the inner response of the main resource signed exchange (article.html.sxg) +has a preload header and an allowed-alt-sxg header: + +``` +Link: ; + rel="preload"; + as="script" +Link: ; + rel="allowed-alt-sxg"; + header-integrity="sha256-XXXXXX" +``` + +The UA recursively prefetches lib.js.sxg. + +If the user navigates to the expected article, both the main resource of the +article and the script subresource are loaded from the prefetched signed +exchanges. + # Proposal +## Privacy-preserving prefetching subresources + 1. Introduce two new cache mechanism SignedExchangeCache and PrefetchedSignedExchangeCache in a Document. - SignedExchangeCache keeps the signed exchanges which are @@ -95,6 +164,27 @@ rel="preload"; as="script"): - After processing the link HTTP headers, clears the PrefetchedSignedExchangeCache. +## Recursive subresource signed exchange prefetch + +While prefetching an HTML resource in signed exchange format: + +1. When the UA detects a "preload" link HTTP header in the inner response, check +whether a matching “allowed-alt-sxg” link HTTP header in the inner response +exists or not. (Note that multiple `allowed-alt-sxg` links can be present for +the same preload if they include `variants` and `variant-key` attributes. In +that case, the UA uses the algorithm written in +[HTTP Representation Variants](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) +spec to find the matching header.) +1. If an `allowed-alt-sxg` link exists, check whether the signed exchange was +served with a matching “alternate” link HTTP header. +1. If the outer signed exchange did identify an alternate version of the +subresource, prefetch the subresource signed exchange instead of prefetching the +original resource URL. +1. The prefetched signed exchange will be stored to the SignedExchangeCache of +the Document. And it will be passed to the next Document and used while +processing the preload link header. This behavior is written in above. + + # Detailed design discussion ## Header integrity of signed exchange The `header-integrity` parameter of the `allowed-alt-sxg` link is the SHA256 @@ -180,6 +270,7 @@ of the signed exchange and Cache-Control header of the outer response. The UA may discard the entry if it is expired. ## Content negotiation using Variants and Variant-Key + The **allowed-alt-sxg** link headers can have [variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) attributes to support content negotiation (eg: @@ -202,17 +293,54 @@ header-integrity is sha256-BBB if available in the cache. Otherwise the UA can use the signed exchange which header-integrity is sha256-AAA if available in the cache. -If the sha256-AAA signed exchange exists in the cache but the sha256-BBB signed -exchange doesn’t exists, the UA which supports WebP format MUST ignore the -sha256-AAA signed exchange and fetch the original URL. Otherwise this can be +When the sha256-AAA signed exchange exists in the cache but the sha256-BBB +signed exchange doesn’t exists, the UA which supports WebP format MUST ignore +the sha256-AAA signed exchange and fetch the original URL. Otherwise this can be used for sending tracking ID. +The **alternate** link also can have +[variants and variant-key](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) +attributes to support content negotiation for recursive prefetch. + +- In **outer** HTTP response of article.html.sxg from feed.example: + ``` + Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/jpeg"; + anchor="https://publisher.example/image"; + Link: ; + rel="alternate"; + type="application/signed-exchange;v=b3"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/webp"; + anchor="https://publisher.example/image"; + ``` +- In **inner** response header of article.html.sxg: + ``` + Link: ; + rel="allowed-alt-sxg"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/jpeg"; + header-integrity="sha256-AAA" + Link: ; + rel="allowed-alt-sxg"; + variants-05="accept;image/jpeg;image/webp"; + variant-key-05="image/webp"; + header-integrity="sha256-BBB" + Link: ; rel=preload; as=image; + ``` +If a UA supports WebP, the UA should prefetch **image_webp.sxg** which content +is WebP format. Otherwise the UA should prefetch **image_jpeg.sxg** which +content is JPEG format. + ## Security and Privacy Considerations - The publishers can know whether the referrer page has prefetched the signed exchange subresources or not by checking the resource timing information. But this only exposes 1 bit information (= yes or no) because UAs can use the cached signed exchange only if the required signed exchanges are all available. -- The UA can use the prefetched signed exchange subresources, only when they +- The UA can use the prefetched signed exchange subresources, only when they were prefetched in the referrer page. This is intended to avoid leaking the prefetching state to succeeding pages. - The UA check the header integrity value, so the distributor of the subresource @@ -231,6 +359,13 @@ href="https://cdn.feed.example/cdn.publisher.example/lib.js.sxg" as="script">`) even if there is the original subresource (http://cdn.publisher.example/lib.js) in the HTTPCache. Otherwise it leaks the state of publisher’s site to the distributor of the signed exchange. +- The UA must fetch the alternate signed exchange subresource (lib.js.sxg) even +if there is the original subresource (lib.js) in the HTTPCache. Otherwise it +leaks the state of publisher’s site to the distributor of the signed exchange. +- To prevent tracking (user ID transfer), if the aggregator failed to prefetch a +subresource that the main resource preloads, the UA must drop all of the +subresource prefetches. If the aggregator prefetches a superset of the preloaded +subresources, the UA must drop the ones that weren't preloaded. - The UA must ignore the not-yet-completed subresource signed exchange prefetch to prevent distributors from interfering the publisher’s page. (Eg. Intentionally block or delay the subresource loading.) So if the user clicks the @@ -245,8 +380,7 @@ before start loading subresources. ## [Self-Review Questionnaire: Security and Privacy](https://www.w3.org/TR/security-privacy-questionnaire/) 1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? - - This feature exposes the 1 bit information "the referrer page has - prefetched the signed exchange subresources or not" to the publisher. + - The existence of the alternative signed exchange in HTTP Cache is exposed. 1. Is this specification exposing the minimum amount of information necessary to power the feature? - Yes. This proposal has limitations such as "all subresource SXG must be @@ -257,22 +391,29 @@ personally-identifiable information or information derived thereof? - Signed Exchange should not include personal information. 1. How does this specification deal with sensitive information? - Signed Exchange should not include sensitive information. + - The state of the cache for another origin is potentially sensitive, and + this specification avoids exposing it by making the decision to fetch an + alternative not depend on the presence or absence of the subresource in its + cache. 1. Does this specification introduce new state for an origin that persists across browsing sessions? - - No. The prefetched signed exchange subresources can be used only from the - pages which are navigated from the document which prefetched them. + - Prefetched resources, including signed exchanges, are stored to the HTTP + cache as normal, but the association of a signed exchange with its contained + resource is not persisted. Right now, the contained resource is not + independently stored in the HTTP cache, although that decision may be + revisited. 1. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? - - This exposes whether the UA support this feature or not. + - The use of Variants exposes the UA's content negotiation preferences to the + aggregator's origin, but that's already exposed by the UA's Accept headers. 1. Does this specification allow an origin access to sensors on a user’s device - No 1. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. - - This feature exposes the 1 bit information "the referrer page has - prefetched the signed exchange subresources or not" to the publisher. - - Sending 1 bit information from the distributor to the publisher is already - easily possible just by changing the URL. + - The existence of the alternative signed exchange in HTTP Cache is exposed. + - But this is the same as the existing behavior when directly prefetching the + signed exchange using ``. 1. Does this specification enable new script execution/loading mechanisms? - This specification introduces a new script loading path, from prefetched signed exchange. The existing security checks such as CSP/CORP must be @@ -284,11 +425,14 @@ agent’s native UI? - No 1. What temporary identifiers might this this specification create or expose to the web? - - No + - None 1. How does this specification distinguish between behavior in first-party and third-party contexts? - This feature treats all entities (the distributor of signed exchange, the publisher site, the origin of subresource URL) as third-party origins. + - To avoid leaking the state of publisher’s site to the distributor of the + signed exchange, the UA must fetch the alternate signed exchange subresource + even if there is the original subresource in the HTTPCache. - To avoid leaking user-specific data in the distributor of signed exchange, the prefetch request must not contain credentials. This is covered by the "Prefetch and double-key caching" issue. @@ -305,5 +449,7 @@ Browsing or "incognito" mode? Considerations" section? - Yes 1. Does this specification allow downgrading default security characteristics? - - No + - There's active discussion about how signed exchanges are a downgrade + compared to TLS, and this particular specification allows recursive use of + signed exchanges. From 82bbcba2b7fc2b33341caa2a628c7c769b7096e5 Mon Sep 17 00:00:00 2001 From: Tsuyoshi Horo Date: Tue, 10 Dec 2019 18:22:29 +0900 Subject: [PATCH 5/6] Incorporated jyasskin's comment --- ...hange-subresource-subtitution-explainer.md | 416 ++++++++---------- 1 file changed, 183 insertions(+), 233 deletions(-) diff --git a/explainers/signed-exchange-subresource-subtitution-explainer.md b/explainers/signed-exchange-subresource-subtitution-explainer.md index fb9b5566..401e52a7 100644 --- a/explainers/signed-exchange-subresource-subtitution-explainer.md +++ b/explainers/signed-exchange-subresource-subtitution-explainer.md @@ -2,85 +2,41 @@ ## Introduction -We want to allow content publishers to declare that the UA can load the specific -subresources from cached signed exchanges which were prefetched in the referrer -page. So we propose a new **rel=allowed-alt-sxg** link HTTP header. - -And also we want to allow the publisher of a resource to declare that a signed -exchange is available holding the content of either that resource or one of its -subresources. We expect aggregator sites (social networks, news sites, search -engines, etc.) to use this to cache the signed version of a resource in order to -serve it to their users. When the -publisher identifies a same-origin signed exchange for a cross-origin -subresource, the UA can use that information to recursively prefetch the -subresource without exposing its speculative activity across origins. - -[``](https://html.spec.whatwg.org/multipage/links.html#rel-alternate) -and the equivalent `Link` header are already defined to declare that the -referenced document is a reformulation of the current document as a signed -exchange. To offer signed exchanges for subresources, we propose to use the -[`anchor` parameter](https://tools.ietf.org/html/rfc8288#section-3.2) to -identify the replaceable subresource. This may be the first use of the `anchor` -parameter in the web platform. - +Users want to see the result of their clicks as fast as possible. This goal +benefits from letting a site tell the UA to +[`prenavigate`](https://github.com/w3c/resource-hints/issues/82#issuecomment-532072736) +to the particular outbound link(s) it thinks the user is most likely to click +on. However, naively prenavigating to a cross-origin link +[leaks that user visited](https://wicg.github.io/webpackage/draft-yasskin-wpack-use-cases.html#name-privacy-preserving-prefetch) +the referring page, which the referrer shouldn't do before the user has clicked. +The referrer can safely prenavigate to a referrer-origin signed exchange for the +top-level HTML of that link, but the UA still can't prefetch that link's +subresources without leaking the same information about the user. + +We want the referrer to be able to identify that a particular subresource of a +prenavigated link is available as a signed exchange served by their own +organization. The +[`Link: ; rel="alternate", type="application/signed-exchange"; anchor="subresource"` header](https://html.spec.whatwg.org/multipage/links.html#rel-alternate) +is already defined to identify such alternate forms, where the +[`anchor` parameter](https://tools.ietf.org/html/rfc8288#section-3.2) states +that the alternate form is for a resource other than the one the `Link` header +is attached to. + +Arbitrarily replacing a target link's subresources is unsafe for several +reasons, so we propose that the target link opt into particular replacements by +including a link with `rel=allowed-alt-sxg`. ## Use Cases -### Privacy-preserving prefetching subresources - -A user is browsing a news feed site (https://feed.example/). The user clicks a -link to an article in another site (https://publisher.example/article.html). The -article is using a large JS library (https://cdn.publisher.example/lib.js) and -the user must wait for the JS file to be fetched from the server to read the -article. - -If the feed site knows that the article is depending on the JS file, the site -can insert a link element (``) to prefetch the JS -file while the user is browsing the feed site. But this leaks that the user's -feed pages include a page using this JS library before the user has -consented by clicking on the link. - -There is an ongoing -[spec discussion](https://github.com/w3c/resource-hints/issues/82) to make -cross-origin navigation prefetch work with double key caching which is proposed -to protect against -[HTTP Cache Cross-Site Leaks](http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html). But as long as the UA needs to fetch the -resource from the publisher's server, this -[privacy leak problem](https://wicg.github.io/webpackage/draft-yasskin-wpack-use-cases.html#private-prefetch) - can't be solved. - -Signed Exchange solve this privacy-preserving prefetching problem for main -resources. If the publisher is providing the article in signed exchange format -(article.html.sxg), the UA can prefetch the signed exchange from the feed site’s -own server while the user is browsing the feed site. But there is no way to -prefetch subresources in a privacy-preserving manner yet. - -Our proposal can solve this problem for subresources: -1. The publisher provides the script file in signed exchange format -(lib.js.sxg). -1. The UA prefetches the signed exchange of the script from the feed site’s own -server while the user is browsing the feed site. -1. The HTTP response of the article from the publisher's server -(https://publisher.example/article.html) has an `allowed-alt-sxg` link header to -declare exactly what version of the subresource is compatible with this main -resource. - ``` - Link: ; - rel="allowed-alt-sxg"; - header-integrity="sha256-..." - ``` - - -### Recursive subresource signed exchange prefetch - While a user is browsing an aggregator site (https://feed.example), the aggregator guesses that the user is likely to want to read a particular article (https://publisher.example/article.html) and so inserts a prefetch link pointing to a signed exchange version of that article. - ``` - - ``` + +``` + +``` + When the UA prefetches the signed exchange (article.html.sxg), the aggregator server includes a declaration that one of `article.html`'s subresources (https://cdn.publisher.example/lib.js) is also available from the same @@ -122,73 +78,70 @@ exchanges. # Proposal -## Privacy-preserving prefetching subresources - -1. Introduce two new cache mechanism SignedExchangeCache and -PrefetchedSignedExchangeCache in a Document. - - SignedExchangeCache keeps the signed exchanges which are -prefetched from the Document. - - PrefetchedSignedExchangeCache keeps the signed -exchanges which were passed from the referrer Document which triggered the -navigation to the current Document. -1. While processing -"[prefetch](https://html.spec.whatwg.org/multipage/links.html#link-type-prefetch)" -link (eg: ``): - - If succeeded prefetching the signed exchange (including merkle integrity - check of the body), stores the parsedExchange which is the result of - [parsing a signed exchange](https://wicg.github.io/webpackage/loading.html#ref-for-parsing-a-signed-exchange) - (= inner request URL and inner response) to the SignedExchangeCache. -1. While +- While prenavigating an HTML resource in signed exchange format: + 1. When the UA detects a "preload" link HTTP header in the inner response, + check whether a matching “allowed-alt-sxg” link HTTP header in the inner + response exists or not. (Note that multiple `allowed-alt-sxg` links can be + present for the same preload if they include `variants` and `variant-key` + attributes. In that case, the UA uses the algorithm written in + [HTTP Representation Variants](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) + spec to find the matching header.) + 1. If an `allowed-alt-sxg` link exists, check whether the signed exchange + was served with a matching “alternate” link HTTP header. + 1. If the outer signed exchange did identify an alternate version of the + subresource, prefetch the subresource signed exchange instead of prefetching + the original resource URL. + 1. If the UA successfully prefetches the signed exchange (including the + merkle integrity check of the body), it stores the parsedExchange which is + the result of + [parsing a signed exchange](https://wicg.github.io/webpackage/loading.html#parsing-a-signed-exchange) + (= inner request URL and inner response) to a new cache mechanism which is + attached to the Document. +- While [navigating across documents](https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigating-across-documents), -copy the parsedExchanges in the SignedExchangeCache of the source document to -the PrefetchedSignedExchangeCache of the target document. This is intended to -provide a way to pass the cached signed exchange across origins even if the UA -is using origin isolated HTTPCache mechanism. -1. While processing +the UA copies the parsedExchanges in the cache of the source document to the +target document except for the one that serves the navigation itself. + - This is intended to provide a way to transfer the cached signed exchange + across origins even if the UA is using origin isolated HTTPCache mechanism. + (Note that [header integrity check](#header-integrity-of-signed-exchange) + prohibits the distributor from passing a tracking ID to the publisher.) +- The navigated-to document has a set of preloads for which it uses the +allowed-alt-sxg link relation to declare that they can be served by signed +exchanges. The UA either serves all of them from SXGs prefetched by the previous +page, or none of them. So while processing [preload](https://html.spec.whatwg.org/multipage/links.html#link-type-preload) link HTTP headers (eg: Link: ; rel="preload"; as="script"): - - Check whether matching "allowed-alt-sxg" link HTTP header - (`Link: ;rel="allowed-alt-sxg";header-integrity="sha256-.."`) - exists or not. (Note that if the allowed-alt-sxg link HTTP header has - variants and variant-key attributes, the UA must execute the algorithm - written in - [HTTP Representation Variants spec](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) - to find the matching header.) - - Check whether all preload links which have matching allowed-alt-sxg link - header have matching (url and header-integrity) parsedExchange in - PrefetchedSignedExchangeCache. If the check passes, set request's stashed - exchange to the parsedExchange so the resource will be loaded from the cached - signed exchange. - - After processing the link HTTP headers, clears the - PrefetchedSignedExchangeCache. - -## Recursive subresource signed exchange prefetch - -While prefetching an HTML resource in signed exchange format: - -1. When the UA detects a "preload" link HTTP header in the inner response, check -whether a matching “allowed-alt-sxg” link HTTP header in the inner response -exists or not. (Note that multiple `allowed-alt-sxg` links can be present for -the same preload if they include `variants` and `variant-key` attributes. In -that case, the UA uses the algorithm written in -[HTTP Representation Variants](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) -spec to find the matching header.) -1. If an `allowed-alt-sxg` link exists, check whether the signed exchange was -served with a matching “alternate” link HTTP header. -1. If the outer signed exchange did identify an alternate version of the -subresource, prefetch the subresource signed exchange instead of prefetching the -original resource URL. -1. The prefetched signed exchange will be stored to the SignedExchangeCache of -the Document. And it will be passed to the next Document and used while -processing the preload link header. This behavior is written in above. - + 1. The UA checks whether matching "allowed-alt-sxg" link HTTP header + (`Link: ;rel="allowed-alt-sxg";header-integrity="sha256-.."`) + exists or not. (Note that if the allowed-alt-sxg link HTTP header has + variants and variant-key attributes, the UA must execute the algorithm + written in + [HTTP Representation Variants spec](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) + to find the matching header.) + 1. The UA checks whether all preload links which have matching + allowed-alt-sxg link header have matching (url and header-integrity) + parsedExchange which was copied from the referrer page. + 1. If the check passes, in "linked resource fetch setup steps" for all + preload links which have matching allowed-alt-sxg link header the UA sets + request's stashed exchange to the matching parsedExchange so the resource + will be loaded from the cached signed exchange. # Detailed design discussion ## Header integrity of signed exchange -The `header-integrity` parameter of the `allowed-alt-sxg` link is the SHA256 -hash value of the *signedHeaders* value from the +We propose a new `rel="allowed-alt-sxg"` link header with a `header-integrity` +parameter. Publishers can declare that the subresource can be served by a signed +exchange, using this link header in the inner response of the main resource +signed exchange. + +``` +Link: ; + rel="allowed-alt-sxg"; + header-integrity="sha256-XXXXXX" +``` + +This `header-integrity` parameter is the SHA256 hash value of the +*signedHeaders* value from the [application/signed-exchange format](https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange) for integrity checking. This signedHeaders is *"the canonical serialization of the CBOR representation of the response headers of the exchange represented by @@ -212,20 +165,21 @@ track the users by changing content-type and detecting the image loading failure. ## Multiple subresource signed exchanges -If there are multiple matching subresource signed exchanges (example: -script.js.sxg and image.jpg.sxg), the UA must check that there is no error in -the all signed exchanges (eg: sig matching, URL matching, Merkle Integrity -error) before processing the content of the signed exchanges. This means that -the UA can use the subresource signed exchanges only when they are defined in -the header. This is intended to prevent the distributor from encoding a tracking -ID into the set of subresources it prefetches. And to prevent the distributor -from selecting a version of the subresource that isn't compatible with the -selected version of the main resource, which might introduce a security hole. - -## Can’t we have a global SignedExchangeCache? -If we can have a global SignedExchangeCache, we can use the all signed exchanges -which have previously prefetched, even if they are not prefetched by the -referrer page. This can improve the performance. But this introduces privacy +If there are multiple subresource preloads that are provided by prefetches on +the previous page in signed exchange format (example: script.js.sxg and +image.jpg.sxg), the UA must check that there is no error in the any of the +signed exchanges (eg: sig matching, URL matching, Merkle Integrity error) before +processing the content of the signed exchanges. This is intended to prevent the +distributor from encoding a tracking ID into the set of subresources it +prefetches. And to prevent the distributor from selecting a version of the +subresource that isn't compatible with the selected version of the main +resource, which might introduce a security hole. + + +## Can’t we have a global cache of parsedExchanges? +If we can have a global cache of parsedExchanges, we can use the all signed +exchanges which have previously prefetched, even if they are not prefetched by +the referrer page. This can improve the performance. But this introduces privacy issues such as [Timing Leaks](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#cache_timing) and [Deterministic History Leaks](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#history_leaks) @@ -236,9 +190,13 @@ the signed exchanges which were prefetched by the referrer page. ## Can’t we merge allowed-alt-sxg to preload header? If we can declare the header-integrity value in the existing preload link HTTP -header, we don’t need to introduce a new "allowed-alt-sxg" link HTTP header. But -it becomes complicated when supporting the -[imagesrcset attribute of preload link](https://github.com/w3c/preload/issues/120). +header, we don’t need to introduce a new "allowed-alt-sxg" link HTTP header. +However, the [imagesrcset attribute](https://github.com/w3c/preload/issues/120) +allows a single preload link to declare multiple different target URLs, and it's +difficult to embed a `header-integrity` value for each of those URLs into the +existing syntax. Instead, we use a separate link that gives a hash of the +expected content for each of the possible URLs, while the preload tag continues +to select which of the URLs is actually used. For Example: ``` @@ -248,13 +206,6 @@ Link: ; imagesrcset="https://publisher.example/wide.jpg 640w, https://publisher.example/narrow.jpg 320w"; imagesizes="(max-width: 640px) 100vw, 640px" -``` -In this case, we want to declare that both wide.jpg and narrow.jpg can be loaded -from signed exchanges and the header-integrity is sha256-XXX and sha256-YYY. But -how to express in this preload link header? - -In our proposal, we can have two allowed-alt-sxg link headers. -``` Link: ; rel="allowed-alt-sxg"; header-integrity="sha256-XXX" @@ -331,125 +282,124 @@ attributes to support content negotiation for recursive prefetch. header-integrity="sha256-BBB" Link: ; rel=preload; as=image; ``` -If a UA supports WebP, the UA should prefetch **image_webp.sxg** which content -is WebP format. Otherwise the UA should prefetch **image_jpeg.sxg** which -content is JPEG format. +If a UA supports WebP, the UA must prefetch **image_webp.sxg** holding a WebP +image. Otherwise the UA must prefetch **image_jpeg.sxg** holding a JPEG image. ## Security and Privacy Considerations - The publishers can know whether the referrer page has prefetched the signed exchange subresources or not by checking the resource timing information. But this only exposes 1 bit information (= yes or no) because UAs can use the cached signed exchange only if the required signed exchanges are all available. +- To prevent tracking (user ID transfer), if the aggregator failed to prefetch a +subresource that the main resource preloads, the UA must drop all of the +subresource prefetches. If the aggregator prefetches a superset of the preloaded +subresources, the UA must drop the ones that weren't preloaded. - The UA can use the prefetched signed exchange subresources, only when they -were prefetched in the referrer page. This is intended to avoid leaking the -prefetching state to succeeding pages. +were prefetched in the rimmediate eferrer page. This is intended to avoid +leaking the prefetching state to succeeding pages. - The UA check the header integrity value, so the distributor of the subresource signed exchange can’t inject arbitrary resources to the publisher’s page. This prevents distributors from sending tracking IDs to the publisher’s page. -- The UA need to check both -[the request URL](https://wicg.github.io/webpackage/loading.html#exchange-request-url) -and the header integrity value of the signed exchange to avoid -[Origin Laundering](https://hillbrad.github.io/sri-addressable-caching/sri-addressable-caching.html#origin_laundering) -attack. The URL is not in signedHeaders, so the header integrity value can’t -check the URL is correct. +- The UA needs to check that the signed +[request URL](https://wicg.github.io/webpackage/loading.html#exchange-request-url) +matches the preload link and not just that the header-integrity value matches, +since the header-integrity hash doesn't cover the request URL. - The UA must fetch the signed exchange subresource (https://cdn.feed.example/cdn.publisher.example/lib.js.sxg) while processing the prefetch link element (``) -even if there is the original subresource (http://cdn.publisher.example/lib.js) -in the HTTPCache. Otherwise it leaks the state of publisher’s site to the -distributor of the signed exchange. -- The UA must fetch the alternate signed exchange subresource (lib.js.sxg) even -if there is the original subresource (lib.js) in the HTTPCache. Otherwise it -leaks the state of publisher’s site to the distributor of the signed exchange. -- To prevent tracking (user ID transfer), if the aggregator failed to prefetch a -subresource that the main resource preloads, the UA must drop all of the -subresource prefetches. If the aggregator prefetches a superset of the preloaded -subresources, the UA must drop the ones that weren't preloaded. -- The UA must ignore the not-yet-completed subresource signed exchange prefetch -to prevent distributors from interfering the publisher’s page. (Eg. -Intentionally block or delay the subresource loading.) So if the user clicks the -link to the article while the UA is still prefetching the subresource signed -exchange, the UA must fetch the subresource from the original URL after -navigation. -- The UA can use the prefetched signed exchange subresources only if the preload -HTTP link headers for the subresources exist in the response headers. It is -because the UA need to check the availability of all required signed exchanges -before start loading subresources. +even if the HTTP cache already contains the original subresource +(http://cdn.publisher.example/lib.js). Otherwise it leaks the state of +publisher’s site to the distributor of the signed exchange. +- If a replaced subresource prefetch hasn't completed by the time the UA would +start fetching it in the course of loading the next page, the UA must cancel +that prefetch and fetch the resource from its original URL. This prevents the +distributor from interfering the publisher’s page. (Eg. intentionally block or +delay the subresource loading.) ## [Self-Review Questionnaire: Security and Privacy](https://www.w3.org/TR/security-privacy-questionnaire/) 1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? - - The existence of the alternative signed exchange in HTTP Cache is exposed. + - This feature exposes the 1 bit information "the referrer page has + prefetched the signed exchange subresources or not" to the publisher. 1. Is this specification exposing the minimum amount of information necessary to power the feature? - - Yes. This proposal has limitations such as "all subresource SXG must be - finished prefetching, otherwise ignored", "subresource SXG must be prefetched - even if the original subresource exists in HTTPCache". + - Yes. This proposal has limitations such as "all subresource SXG must be + finished prefetching, otherwise ignored", "subresource SXG must be prefetched + even if the original subresource exists in HTTPCache". Thanks to these + limitations, this feature exposes only 1 bit information to the publisher. 1. How does this specification deal with personal information or personally-identifiable information or information derived thereof? - - Signed Exchange should not include personal information. + - Signed Exchange should not include personal information. + - Any personal information that was incorrectly included in a signed + exchange would be the information of the aggregator that fetched the SXG, + and not the end user. + - The use of `` to identify the SXG for the current page + could inform the UA to omit credentials in fetching that SXG, which would + prevent any personal information from being accidentally included. 1. How does this specification deal with sensitive information? - - Signed Exchange should not include sensitive information. - - The state of the cache for another origin is potentially sensitive, and - this specification avoids exposing it by making the decision to fetch an - alternative not depend on the presence or absence of the subresource in its - cache. + - Signed Exchange should not include sensitive information. + - The state of the cache for another origin is potentially sensitive, and + this specification avoids exposing it by making the decision to fetch an + alternative not depend on the presence or absence of the subresource in its + cache. 1. Does this specification introduce new state for an origin that persists across browsing sessions? - - Prefetched resources, including signed exchanges, are stored to the HTTP - cache as normal, but the association of a signed exchange with its contained - resource is not persisted. Right now, the contained resource is not - independently stored in the HTTP cache, although that decision may be - revisited. + - Prefetched resources, including signed exchanges, are stored to the HTTP + cache as normal, but the association of a signed exchange with its contained + resource is not persisted. Right now, the contained resource is not + independently stored in the HTTP cache, although that decision may be + revisited. 1. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? - - The use of Variants exposes the UA's content negotiation preferences to the - aggregator's origin, but that's already exposed by the UA's Accept headers. + - The use of Variants exposes the UA's content negotiation preferences to + the aggregator's origin, but that's already exposed by the UA's Accept + headers. 1. Does this specification allow an origin access to sensors on a user’s device - - No + - No 1. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. - - The existence of the alternative signed exchange in HTTP Cache is exposed. - - But this is the same as the existing behavior when directly prefetching the - signed exchange using ``. + - The existence of the alternative signed exchange in HTTP Cache is exposed. + - But this is the same as the existing behavior when directly prefetching the + signed exchange using ``. 1. Does this specification enable new script execution/loading mechanisms? - - This specification introduces a new script loading path, from prefetched - signed exchange. The existing security checks such as CSP/CORP must be - applied as if the script is loaded from the original URL. + - This specification introduces a new script loading path, from prefetched + signed exchange. The existing security checks such as CSP/CORP must be + applied as if the script is loaded from the original URL. 1. Does this specification allow an origin to access other devices? - - No + - No 1. Does this specification allow an origin some measure of control over a user agent’s native UI? - - No + - No 1. What temporary identifiers might this this specification create or expose to the web? - - None + - None 1. How does this specification distinguish between behavior in first-party and third-party contexts? - - This feature treats all entities (the distributor of signed exchange, the - publisher site, the origin of subresource URL) as third-party origins. - - To avoid leaking the state of publisher’s site to the distributor of the - signed exchange, the UA must fetch the alternate signed exchange subresource - even if there is the original subresource in the HTTPCache. - - To avoid leaking user-specific data in the distributor of signed exchange, - the prefetch request must not contain credentials. This is covered by the - "Prefetch and double-key caching" issue. - - The origin of subresource URL could be different from the origin of - publisher site. The cross origin security checks (CORS/CORB/CORP/..) must be - executed while reading the response from the cached signed exchanges. + - This feature treats all entities (the distributor of signed exchange, the + publisher site, the origin of subresource URL) as third-party origins. + - To avoid leaking the state of publisher’s site to the distributor of the + signed exchange, the UA must fetch the alternate signed exchange subresource + even if there is the original subresource in the HTTPCache. + - To avoid leaking user-specific data in the distributor of signed exchange, + the prefetch request must not contain credentials. This is covered by the + "Prefetch and double-key caching" + [issue](https://github.com/w3c/resource-hints/issues/82). + - The origin of subresource URL could be different from the origin of + publisher site. The cross origin security checks (CORS/CORB/CORP/..) must be + executed while reading the response from the cached signed exchanges. 1. How does this specification work in the context of a user agent’s Private Browsing or "incognito" mode? - - No difference while the user is browsing sites in Private mode. - - If the user opens a link in private mode while browsing in normal mode (eg: - "Open link in incognito window"), the prefetched signed exchanges must be - ignored. + - No difference while the user is browsing sites in Private mode. + - If the user opens a link in private mode while browsing in normal mode + (eg: "Open link in incognito window"), the prefetched signed exchanges must + be ignored. 1. Does this specification have a "Security Considerations" and "Privacy Considerations" section? - - Yes + - Yes 1. Does this specification allow downgrading default security characteristics? - - There's active discussion about how signed exchanges are a downgrade - compared to TLS, and this particular specification allows recursive use of - signed exchanges. + - There's active discussion about how signed exchanges are a downgrade + compared to TLS, and this particular specification allows recursive use of + signed exchanges. From a67da352a41a99e7481c1cd7b3737615476315c2 Mon Sep 17 00:00:00 2001 From: Tsuyoshi Horo Date: Mon, 23 Dec 2019 17:22:36 +0900 Subject: [PATCH 6/6] Incorporated jyasskin's comment --- ...hange-subresource-subtitution-explainer.md | 136 ++++++++---------- 1 file changed, 56 insertions(+), 80 deletions(-) diff --git a/explainers/signed-exchange-subresource-subtitution-explainer.md b/explainers/signed-exchange-subresource-subtitution-explainer.md index 401e52a7..a08049c9 100644 --- a/explainers/signed-exchange-subresource-subtitution-explainer.md +++ b/explainers/signed-exchange-subresource-subtitution-explainer.md @@ -31,7 +31,9 @@ including a link with `rel=allowed-alt-sxg`. While a user is browsing an aggregator site (https://feed.example), the aggregator guesses that the user is likely to want to read a particular article (https://publisher.example/article.html) and so inserts a prefetch link pointing -to a signed exchange version of that article. +to a signed exchange version of that article. (Note: A new rel type +`prenavigate` for prenavigation is under +[discussion](https://github.com/w3c/resource-hints/issues/82#issuecomment-532072736).) ``` @@ -56,10 +58,10 @@ the replacement signed exchange using a `Link: ... rel="allowed-alt-sxg"` with the hash of the signed headers (which themselves include a hash of the content). To prevent a tracker from conveying a user ID in their choice of which -subresources to prefetch, the inner resource has to preload the same +subresources to prefetch, the inner resource also has to preload the same subresources that the aggregator prefetches. -And the inner response of the main resource signed exchange (article.html.sxg) -has a preload header and an allowed-alt-sxg header: +This means that the inner response of the main resource signed exchange +(article.html.sxg) has a preload header and an allowed-alt-sxg header: ``` Link: ; @@ -76,9 +78,11 @@ If the user navigates to the expected article, both the main resource of the article and the script subresource are loaded from the prefetched signed exchanges. -# Proposal +# Algorithm sketch -- While prenavigating an HTML resource in signed exchange format: +- While +[prenavigating](https://github.com/w3c/resource-hints/issues/82#issuecomment-532072736) + an HTML resource in signed exchange format: 1. When the UA detects a "preload" link HTTP header in the inner response, check whether a matching “allowed-alt-sxg” link HTTP header in the inner response exists or not. (Note that multiple `allowed-alt-sxg` links can be @@ -89,22 +93,16 @@ exchanges. 1. If an `allowed-alt-sxg` link exists, check whether the signed exchange was served with a matching “alternate” link HTTP header. 1. If the outer signed exchange did identify an alternate version of the - subresource, prefetch the subresource signed exchange instead of prefetching - the original resource URL. - 1. If the UA successfully prefetches the signed exchange (including the - merkle integrity check of the body), it stores the parsedExchange which is - the result of - [parsing a signed exchange](https://wicg.github.io/webpackage/loading.html#parsing-a-signed-exchange) - (= inner request URL and inner response) to a new cache mechanism which is - attached to the Document. + subresource, prefetch the subresource signed exchange. + 1. If the resulting signed exchange is valid and matches the allowed-alt-sxg + link, attach it to the top-level prefetch. - While [navigating across documents](https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigating-across-documents), -the UA copies the parsedExchanges in the cache of the source document to the -target document except for the one that serves the navigation itself. - - This is intended to provide a way to transfer the cached signed exchange - across origins even if the UA is using origin isolated HTTPCache mechanism. - (Note that [header integrity check](#header-integrity-of-signed-exchange) - prohibits the distributor from passing a tracking ID to the publisher.) +the UA copies the signed exchanges that were prefetched above to the target +document except for the one that serves the navigation itself. + - Note that as browsers move toward partitioned HTTP caches, the source + document's cache will likely be separate from the target's cache, so we + can't just pass prefetched content through the cache. - The navigated-to document has a set of preloads for which it uses the allowed-alt-sxg link relation to declare that they can be served by signed exchanges. The UA either serves all of them from SXGs prefetched by the previous @@ -112,23 +110,19 @@ page, or none of them. So while processing [preload](https://html.spec.whatwg.org/multipage/links.html#link-type-preload) link HTTP headers (eg: Link: ; rel="preload"; as="script"): - 1. The UA checks whether matching "allowed-alt-sxg" link HTTP header - (`Link: ;rel="allowed-alt-sxg";header-integrity="sha256-.."`) - exists or not. (Note that if the allowed-alt-sxg link HTTP header has - variants and variant-key attributes, the UA must execute the algorithm - written in - [HTTP Representation Variants spec](https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html) - to find the matching header.) - 1. The UA checks whether all preload links which have matching - allowed-alt-sxg link header have matching (url and header-integrity) - parsedExchange which was copied from the referrer page. - 1. If the check passes, in "linked resource fetch setup steps" for all - preload links which have matching allowed-alt-sxg link header the UA sets - request's stashed exchange to the matching parsedExchange so the resource - will be loaded from the cached signed exchange. + 1. For each preload, use the imagesrcset and imagesizes attributes to pick a + single URL to preload. + 1. Identify the subset _SxgPreloads_ of those preloads with an + `allowed-alt-sxg` link for that selected URL. + 1. If every member of _SxgPreloads_ has a valid signed exchange that was + transferred from the referring document, use the signed contents of those + resources to satisfy the preloads. Ignore any other prefetched signed + exchanges. + 1. Otherwise, ignore all prefetched signed exchanges and re-fetch the + preloads from their original URLs. # Detailed design discussion -## Header integrity of signed exchange +## Identifying exactly one version of a signed exchange We propose a new `rel="allowed-alt-sxg"` link header with a `header-integrity` parameter. Publishers can declare that the subresource can be served by a signed exchange, using this link header in the inner response of the main resource @@ -147,34 +141,17 @@ for integrity checking. This signedHeaders is *"the canonical serialization of the CBOR representation of the response headers of the exchange represented by the application/signed-exchange resource, excluding the Signature header field"*. So this value doesn’t change even if the publisher signs the content -again or changes the signing key. This header-integrity value also guarantees -the content body hasn't changed, because the signed headers are required to -include a `Digest` header with a hash of the content body. - -The UA needs to check that this value of the prefetched subresource signed -exchange is same as the header-integrity attribute of allowed-alt-sxg link -header in the response from the publisher. This is intended to prevent the -distributor from encoding a tracking ID into the subresource signed exchange. +again or changes the signing key, but it does change if any of the headers or +body change. (It catches changes to the body because a valid signed exchange's +headers have to include a `Digest` value that covers the body.) We can’t use the -[SRI’s integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) -for this purpose, because SRI’s integrity only covers the content body and not -any of the headers. So if the UA use the SRI’s integrity value in -allowed-alt-sxg link header, we can use the subresource signed exchanges to -track the users by changing content-type and detecting the image loading -failure. - -## Multiple subresource signed exchanges -If there are multiple subresource preloads that are provided by prefetches on -the previous page in signed exchange format (example: script.js.sxg and -image.jpg.sxg), the UA must check that there is no error in the any of the -signed exchanges (eg: sig matching, URL matching, Merkle Integrity error) before -processing the content of the signed exchanges. This is intended to prevent the -distributor from encoding a tracking ID into the set of subresources it -prefetches. And to prevent the distributor from selecting a version of the -subresource that isn't compatible with the selected version of the main -resource, which might introduce a security hole. - +[SRI `integrity` attribute](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) +for this purpose, because SRI’s `integrity` attribute only covers the content +body and not any of the headers. So if the UA use the SRI’s integrity value in +`allowed-alt-sxg` link header, a tracker can use signed exchanges that differ in +headers like their `Content-Type` to transfer a user ID via a pattern of parsing +failures. ## Can’t we have a global cache of parsedExchanges? If we can have a global cache of parsedExchanges, we can use the all signed @@ -216,7 +193,7 @@ Link: ; ## Lifetime of the entry in SignedExchangeCache The UA must check both the -[signature expire time](https://wicg.github.io/webpackage/loading.html#exchange-signature-expiration-time) +[signature expiration time](https://wicg.github.io/webpackage/loading.html#exchange-signature-expiration-time) of the signed exchange and Cache-Control header of the outer response. The UA may discard the entry if it is expired. @@ -285,7 +262,7 @@ attributes to support content negotiation for recursive prefetch. If a UA supports WebP, the UA must prefetch **image_webp.sxg** holding a WebP image. Otherwise the UA must prefetch **image_jpeg.sxg** holding a JPEG image. -## Security and Privacy Considerations +# Security and Privacy Considerations - The publishers can know whether the referrer page has prefetched the signed exchange subresources or not by checking the resource timing information. But this only exposes 1 bit information (= yes or no) because UAs can use the cached @@ -295,27 +272,25 @@ subresource that the main resource preloads, the UA must drop all of the subresource prefetches. If the aggregator prefetches a superset of the preloaded subresources, the UA must drop the ones that weren't preloaded. - The UA can use the prefetched signed exchange subresources, only when they -were prefetched in the rimmediate eferrer page. This is intended to avoid +were prefetched in the immediate referrer page. This is intended to avoid leaking the prefetching state to succeeding pages. -- The UA check the header integrity value, so the distributor of the subresource -signed exchange can’t inject arbitrary resources to the publisher’s page. This -prevents distributors from sending tracking IDs to the publisher’s page. +- The UA checks the header integrity value, so the distributor of the +subresource signed exchange can’t inject arbitrary resources to the publisher’s +page. This prevents distributors from sending mismatched versions or tracking +IDs to the publisher’s page. - The UA needs to check that the signed [request URL](https://wicg.github.io/webpackage/loading.html#exchange-request-url) matches the preload link and not just that the header-integrity value matches, since the header-integrity hash doesn't cover the request URL. -- The UA must fetch the signed exchange subresource -(https://cdn.feed.example/cdn.publisher.example/lib.js.sxg) while processing the -prefetch link element (``) -even if the HTTP cache already contains the original subresource -(http://cdn.publisher.example/lib.js). Otherwise it leaks the state of -publisher’s site to the distributor of the signed exchange. +- The UA's decision of whether to fetch signed exchange subresources MUST NOT +depend on whether the HTTP cache already contains the original subresource. +Otherwise it leaks the state of publisher’s site to the distributor of the +signed exchange. - If a replaced subresource prefetch hasn't completed by the time the UA would start fetching it in the course of loading the next page, the UA must cancel that prefetch and fetch the resource from its original URL. This prevents the -distributor from interfering the publisher’s page. (Eg. intentionally block or -delay the subresource loading.) +distributor from interfering the publisher’s page. (Eg. intentionally blocking +or delaying the subresource loading.) ## [Self-Review Questionnaire: Security and Privacy](https://www.w3.org/TR/security-privacy-questionnaire/) 1. What information might this feature expose to Web sites or other parties, and @@ -377,11 +352,12 @@ the web? - None 1. How does this specification distinguish between behavior in first-party and third-party contexts? - - This feature treats all entities (the distributor of signed exchange, the - publisher site, the origin of subresource URL) as third-party origins. + - This feature treats the distributor of signed exchange and the origins of + cross-origin subresources as third-party origins. - To avoid leaking the state of publisher’s site to the distributor of the - signed exchange, the UA must fetch the alternate signed exchange subresource - even if there is the original subresource in the HTTPCache. + signed exchange, the UA's decision of whether to fetch signed exchange + subresources MUST NOT depend on whether the HTTP cache already contains the + original subresource. - To avoid leaking user-specific data in the distributor of signed exchange, the prefetch request must not contain credentials. This is covered by the "Prefetch and double-key caching"