Skip to content

Commit

Permalink
Clarify external speculation rules integration with security features
Browse files Browse the repository at this point in the history
This clarifies the integration with three security features related to external requests:
* Content Security Policy - namely, that external speculation rules, like inline ones, respect the `script-src` directive
* Fetch Metadata - namely, that "speculationrules" is the identifier used for these requests
* Mixed Content - no changes are expressly required, but noting that this is a blockable subresource is still helpful in the Security Considerations section

Chromium already implements all of these changes.
  • Loading branch information
jeremyroman authored Dec 7, 2023
1 parent 83ed30c commit 7d38051
Showing 1 changed file with 29 additions and 2 deletions.
31 changes: 29 additions & 2 deletions speculation-rules.bs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ add the following step
1. [=Assert=]: |pendingResource|'s [=pending external speculation rule resource/controller=] is null.
1. Let |settingsObject| be |document|'s [=relevant settings object=].
1. Let |requestURL| be |pendingResource|'s [=pending external speculation rule resource/URL=].
1. Let |request| be a new [=request=] whose [=request/URL=] is |requestURL|, [=request/client=] is |settingsObject|, and [=request/mode=] is "`cors`".
1. Let |request| be a new [=request=] whose [=request/URL=] is |requestURL|, [=request/client=] is |settingsObject|, [=request/mode=] is "`cors`", and [=request/destination=] is "`speculationrules`".
1. Let |controller| be the result of [=fetching=] given |request| with <i>[=fetch/processResponseConsumeBody=]</i> set to the following steps given [=response=] |response| and null, failure, or a [=byte sequence=] |body|:
1. [=list/Remove=] |pendingResource| from |pendingResources|.
1. If any of the following conditions are true, abort these steps:
Expand Down Expand Up @@ -758,6 +758,19 @@ The algorithm needs patches to handle the "`script speculationrules`" type at th
5. If <a>`type`</a> is "`script`",<ins> "`script speculationrules`",</ins> "`style`",
or |unsafe-hashes flag| is `true`:

<h3 id="content-security-policy-patches-effective-directive">Get the effective directive for request</h3>

The switch needs one additional case. At present, requests can only be issued in the case of the [:Speculation-Rules:] header, so `script-src-elem` is too specific and only `script-src` (or its fallback, `default-src`) applies.

: "`speculationrules`"
:: 1. Return `script-src`.

<h2 id="fetch">Fetch</h2>

<h3 id="fetch-destination">Destination</h3>

The string "`speculationrules`" is added to the list of valid [=request/destinations=] and also to the list of enumerators in {{RequestDestination}}.

<h2 id="security-considerations">Security considerations</h2>

<h3 id="security-csrf">Cross-site request forgery</h3>
Expand All @@ -770,6 +783,12 @@ Otherwise, requests are always issued without using any previously existing [=cr

Because links in a document could be selected using a document rule, if the document may contain user-generated markup then authors should construct their speculation rules to exclude such links that may have harmful side effects, e.g., by using a [=document rule CSS selector predicate=] to exclude links in regions with user-generated links or by using a [=document rule URL pattern predicate=] to allow only URL patterns known to be safe to fetch without side effects.

The [:Speculation-Rules:] header can also cause requests to be issued. These requests are unlikely to be useful in mounting a CSRF attack, because:
* These requests are sent with [=request/credentials mode=] "`same-origin`" (the default), so no stored credentials are included in the request, and such credentials are likely to be required to cause unwanted side effects.
* These requests are unlikely to be useful in inferring the contents of a non-speculation rules resource, because responses with the incorrect MIME type are not honored.
* These requests are unlikely to be useful in inferring the contents of a speculation rules resource, because they are sent with [=request/mode=] "`cors`", and so cross-origin resources must explicitly opt in using [:Access-Control-Allow-Origin:].
* These requests are distinguishable from requests by other causes in the browser because a separate value, "`speculationrules`", is provided in the [:Sec-Fetch-Dest:] request header.

<h3 id="security-xss">Cross-site scripting</h3>

This specification causes activity in response to content found in the document, so it is worth considering the options open to an attacker able to inject unescaped HTML.
Expand All @@ -780,6 +799,8 @@ The same mitigations available to other features also apply here. In particular,

The possibility of leaking link URLs via this mechanism is additionally mitigated by the fact that prefetch and prerender to plaintext HTTP (other than to localhost) is not permitted, and so such an on-path attacker could not directly observe preloading request URLs, but would only have access to metadata and traffic analysis. This does not, however, replace standard XSS protections.

It's generally not expected that user-generated content will be added as arbitrary response headers; server operators are already going to encounter significant trouble if this is possible. It is therefore unlikely that the [:Speculation-Rules:] header meaningfully expands the XSS attack surface. Nonetheless, the [[CSP]] `script-src` directive applies in this case as well.

<h3 id="type-confusion">Type confusion</h3>

In the case of speculation rules in an inline `<script>`, an application which erroneously parsed speculation rules as a JavaScript script (though user agents are instructed not to execute scripts who "`type`" is unrecognized) would either interpret it as the empty block `{}` or produce a syntax error, since the U+003A COLON (`:`) after the first key is invalid JavaScript. In neither case would such an application execute harmful behavior.
Expand All @@ -788,7 +809,7 @@ Since the parsing behavior of the `<script>` element has long been part of HTML,
Authors should, however, still escape any potentially attacker-controlled content inserted into speculation rules. In particular, it may be necessary to escape JSON syntax as well as, if the speculation rules are in an inline `<script>` tag, the closing `</script>` tag. [[CSP]] is a useful additional mitigation for vulnerabilities of this type.

<div class="issue">Expand this section once externally loaded (via "`src`") speculation rules are specified.</div>
Similarly, processing non-speculation rules resources as speculation rules is unlikely because this specification requires implementations to validate that its MIME type has an [=MIME type/essence=] of "`application/speculationrules+json"`.

<h3 id="security-ip-anonymization">IP anonymization</h3>

Expand All @@ -798,6 +819,12 @@ To the extent IP anonymization is implemented using a proxy service, it is advis

Site operators should be aware that, similar to virtual private network (VPN) technology, the client IP address seen by the HTTP server may not exactly correspond to the user's actual network provider or location, and a traffic for multiple distinct subscribers may originate from a single client IP address. This may affect site operators' security and abuse prevention measures. IP anonymization measures may make an effort to use an egress IP address which has a similar geolocation or is located in the same jurisdiction as the user, but any such behavior is particular to the user agent and not guaranteed by this specification.

<h3 id="mixed-content">Mixed content</h3>

Speculation rules are either inline (so are delivered by the same origin as the document) or fetched via the [:Speculation-Rules:] header (in which case they are [=blockable mixed content|blockable=] as part of [=should fetching request be blocked as mixed content?=]).

The speculative actions initiated by this specification may also have similar protections. For example, prefetching of URLs which are not [=potentially trustworthy URL|potentially trustworthy=] is not permitted at all, even from environments which are not themselves [=secure contexts=].

<h2 id="privacy-considerations">Privacy considerations</h2>

<h3 id="privacy-heuristics">Heuristics</h3>
Expand Down

0 comments on commit 7d38051

Please sign in to comment.