1. Speculation rules
1.1. Definitions
A speculation rule is a struct with the following items:
-
URLs, an ordered set of URLs
-
requirements, an ordered set of strings
The only valid string for requirements to contain is "anonymous-client-ip-when-cross-origin
".
A speculation rule set is a struct with the following items:
-
prefetch rules, a list of speculation rules
-
prerender rules, a list of speculation rules
1.2. The script
element
Note: This section contains modifications to the corresponding section of [HTML].
To process speculation rules consistently with the existing script types, we make the following changes:
-
Add "
speculationrules
" to the list of valid values for ascript
element’s type. -
Add a speculation rule set to the list of valid values for a
script
element’s result.
The following algorithms are updated accordingly:
-
Prepare the script element: see § 1.3 Prepare the script element.
-
Execute the script element: Add the following case to the switch on type:
- "
speculationrules
" -
-
Assert: Never reached.
-
- "
We should consider whether we also want to make this execute even if scripting is disabled.
We should also incorporate the case where a src
attribute is set.
We could fire error
and load
events if we wanted to.
-
In
supports(type)
method steps, before-
Return false.
add the following step:
-
If type is "
speculationrules
", then return true.
-
script
element’s HTML element removing steps, given removedNode and oldParent:
-
If removedNode’s result is a speculation rule set, then:
-
Let document be removedNode’s node document.
-
Remove it from document’s list of speculation rule sets.
-
Set removedNode’s already started flag to false.
-
Set removedNode’s result to null.
-
Consider speculation for document.
This means that the rule set can be reparsed if the script is reinserted. -
script
element’s children changed steps for an element scriptElement.
-
If scriptElement’s result is a speculation rule set, then:
-
Let document be scriptElement’s node document.
-
Let ruleSet be scriptElement’s result.
-
Let newResult be the result of parsing speculation rules given scriptElement’s child text content and document’s document base URL.
-
Set scriptElement’s result to newResult.
-
Replace ruleSet with newResult in document’s list of speculation rule sets.
-
Consider speculation for document.
This means that the rule set is reparsed immediately if inline changes are made. -
1.3. Prepare the script element
Inside the prepare the script element algorithm we make the following changes:
-
Insert the following step after the step that checks for an ASCII case-insensitive match for the string "
module
":-
If the script block’s type string is an ASCII case-insensitive match for the string "
speculationrules
", then set el’s type to "speculationrules
".
-
-
Insert the following case in the switch on type within the step which begins "If el does not have a
src
content attribute..."- "
speculationrules
" -
-
Let result be the result of parsing speculation rules given source text and base URL.
-
If result is not null, append it to el’s node document's list of speculation rule sets.
-
Mark as ready el given result.
-
Consider speculation for document.
-
- "
1.4. Parsing
The general principle here is to allow the existence of directives which are not understood, but not to accept into the rule set a rule which the user agent does not fully understand. This reduces the risk of unintended activity by user agents which are unaware of most recently added directives which might limit the scope of a rule.
-
Let parsed be the result of parsing a JSON string to an Infra value given input.
-
If parsed is not a map, then return null.
-
Let result be an empty speculation rule set.
-
If parsed["
prefetch
"] exists and is a list, then for each prefetchRule of parsed["prefetch
"]:-
Let rule be the result of parsing a speculation rule given prefetchRule and baseURL.
-
If rule is null, then continue.
-
Append rule to result’s prefetch rules.
-
If parsed["
prerender
"] exists and is a list, then for each prerenderRule of parsed["prerender
"]:-
Let rule be the result of parsing a speculation rule given prerenderRule and baseURL.
-
If rule is null, then continue.
-
Append rule to result’s prerender rules.
-
Return result.
-
If input has any key other than "
source
", "urls
", and "requires
", then return null. -
If input["
source
"] does not exist or is not the string "list
", then return null. -
Let urls be an empty list.
-
If input["
urls
"] does not exist, is not a list, or has any element which is not a string, then return null. -
For each urlString of input["
urls
"]: -
Let requirements be an empty ordered set.
-
If input["
requires
"] exists, but is not a list, then return null. -
For each requirement of input["
requires
"]: -
Return a speculation rule with URLs urls and requirements requirements.
1.5. Processing model
A document has a list of speculation rule sets, which is an initially empty list.
Periodically, for any document document, the user agent may queue a global task on the DOM manipulation task source with document’s relevant global object to consider speculation for document.
The user agent will likely do when resources are idle and available, or otherwise the circumstances of its previous decision whether to start a speculation could have changed.
A prefetch candidate is a struct with the following items:
-
URL, an URL
-
referrer policy, a referrer policy
-
anonymization policy, a prefetch IP anonymization policy
A prerender candidate is a struct with the following items:
-
URL, an URL
-
referrer policy, a referrer policy
-
Await a stable state. Steps in the synchronous section are marked with ⌛.
-
⌛ If document is not fully active, then return.
It’s likely that we should also handle prerendered and back-forward cached documents.
-
⌛ Let prefetchCandidates be an empty list.
-
⌛ Let prerenderCandidates be an empty list.
-
⌛ For each ruleSet of document’s list of speculation rule sets:
-
⌛ For each rule of ruleSet’s prefetch rules:
-
⌛ Let anonymizationPolicy be null.
-
⌛ If rule’s requirements contains "
anonymous-client-ip-when-cross-origin
", set anonymizationPolicy to a cross-origin prefetch IP anonymization policy whose origin is document’s origin. -
⌛ For each url of rule’s URLs:
-
⌛ Append a prefetch candidate with URL url, referrer policy "
strict-origin-when-cross-origin
", and anonymization policy anonymizationPolicy to prefetchCandidates.
-
-
-
⌛ For each rule of ruleSet’s prerender rules:
-
⌛ For each url of rule’s URLs:
-
⌛ Append a prerender candidate with URL url and referrer policy "
strict-origin-when-cross-origin
" to prerenderCandidates.
-
-
-
-
End the synchronous section, continuing the remaining steps in parallel.
-
For each prefetchCandidate of prefetchCandidates:
-
The user agent may prefetch given document, prefetchCandidate’s URL, prefetchCandidate’s referrer policy and prefetchCandidate’s anonymization policy.
-
-
For each prerenderCandidate of prefetchCandidates:
-
The user agent may create a prerendering browsing context given prerenderCandidate’s URL, prerenderCandidate’s referrer policy and document.
-
We should also notice removals and consider cancelling speculated actions.
We should revisit the referrer policies used here.
2. Security considerations
2.1. Cross-site request forgery
This specification allows documents to cause HTTP requests to be issued.
When any supported action acts on a URL which is same origin to the document, then this does not constitute a risk of cross-site request forgery, since the request uses only the credentials available to the document.
Otherwise, requests are always issued without using any previously existing credentials. This limits the ambient authority available to any potentially forged request, and such requests can already be made through [FETCH], a subresource or frame, or various other means. Site operators are therefore already well-advised to use CSRF tokens or other mitigations for this threat.
2.2. Cross-site scripting
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.
Such an attacker is otherwise able to inject JavaScript, frames or other elements. The activity possible with this specification (requesting fetches etc) is generally less dangerous than arbitrary script execution, and comparable to other elements. The same mitigations available to other features also apply here. In particular, the [CSP] script-src
directive applies to the parsing of the speculation rules and the prefetch-src
directive applies to prefetch requests arising from the rules.
2.3. Type confusion
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.
Since the parsing behavior of the <script>
element has long been part of HTML, any modern HTML parser would not construct any non-text children of the element. There is thus a low risk of other text hidden inside a <script>
element with type="speculationrules"
which is parsed as part of the script content by compliant HTML implementations but as HTML tags by others.
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.
2.4. IP anonymization
This specification allows authors to request prefetch traffic using IP anonymization technology provided by the user agent. The details of this technology are not a part of this specification; nonetheless some general principles apply.
To the extent IP anonymization is implemented using a proxy service, it is advisable to minimize the information available to the service operator and other entities on the network path. This likely involves, at a minimum, the use of [TLS] for the connection.
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.
3. Privacy considerations
3.1. Heuristics
Because the candidate prefetches and other actions are not required, the user agent can use heuristics to determine which actions would be best to execute. Because it may be observable to the document whether actions were executed, user agents must take care to protect privacy when making such decisions — for instance by only using information which is already available to the origin. If these heuristics depend on any persistent state, that state must be erased whenever the user erases other site data. If the user agent automatically clears other site data from time to time, it must erase such persistent state at the same time.
Examples of inputs which would be already known to the document:
-
author-supplied scores (if future version of this specification allows specifying them)
-
order of appearance in the document
-
whether the link is in the viewport
-
whether the cursor is near the link
-
rendered size of the link
Examples of persistent data related to the origin (which the origin could have gathered itself) but which must be erased according to user intent:
-
whether the user has clicked this or similar links on this document or other documents on the same origin
Examples of device information which may be valuable in deciding whether prefetching is appropriate, but which must be considered as part of the user agent’s overall privacy posture because it may make the user more identifiable across origins:
-
coarse device class (CPU, memory)
-
coarse battery level
-
whether the network connection is known to be metered
3.2. Intent
While efforts have been made to minimize the privacy impact of prefetching, some users may nonetheless prefer that prefetching not occur, even though this may make loading slower. User agents are encouraged to provide a setting to disable prefetching features to accommodate such users.
3.3. Partitioning
Some user agents partition storage according to the site or origin of the top-level document. In order for prefetching and prerendering to be useful, it is therefore essential that prefetching or prerendering of a document either occur in the partition in which the navigation would occur (e.g., for a same-origin URL) or in an isolated partition, so as to ensure that prefetching does not become a mechanism for bypassing the partitioning scheme.
3.4. Identity joining
This specification describes a mechanism through which HTTP requests for later top-level navigation (in the case of prefetching) can be made without a user gesture. It is natural to ask whether it is possible for two coordinating sites to connect user identities.
Since existing credentials for the destination origin are not sent (assuming it is not same origin with the referrer), that site is limited in its ability to identify the user before navigation in a similar way to if the referrer site had simply used [FETCH] to make an uncredentialed request. Upon navigation, this becomes similar to ordinary navigation (e.g., by clicking a link that was not prefetched).
To the extent that user agents attempt to mitigate identity joining for ordinary fetches and navigations, they can apply similar mitigations to prefetched navigations.