1. Speculation rules
1.1. Definitions
A speculation rule is a struct with the following items:
-
URLs, an ordered set of URLs
-
predicate, a document rule predicate or null
-
requirements, an ordered set of strings
-
target navigable name hint, a string or null
-
referrer policy, a referrer policy
-
eagerness, one of the valid eagerness strings
-
No-Vary-Search hint, a URL search variance
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
A pending external speculation rule resource is a struct with the following items:
-
URL, a URL
-
controller, a fetch controller or null
A document rule predicate is one of the following:
A document rule conjunction is a struct with the following items:
-
clauses, a list of document rule predicates
A document rule disjunction is a struct with the following items:
-
clauses, a list of document rule predicates
A document rule negation is a struct with the following items:
-
clause, a document rule predicate
A document rule URL pattern predicate is a struct with the following items:
-
patterns, a list of URL patterns
A document rule CSS selector predicate is a struct with the following items:
The following strings are valid eagerness strings: "immediate
", "eager
", "moderate
", "conservative
".
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, document, 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 document be el’s node document
-
Let result be the result of parsing speculation rules given source text, document and base URL.
-
If result is not null, append it to document’s list of speculation rule sets.
-
Mark as ready el given result.
-
Consider speculation for document.
-
- "
-
Replace "script" argument with cspType that is set through the following steps, and passed to Content Security Policy 3 § 4.2.3 Should element’s inline type behavior be blocked by Content Security Policy? algorithm.
-
-
Let cspType be "script".
-
If type is "
speculationrules
", then set cspType to "script speculationrules
".
-
-
1.4. The `Speculation-Rules
` header
Note: This section contains modifications to [HTML].
The Speculation-Rules
HTTP response header is a structured header whose value must be a list whose members must be strings which are valid URL strings.
To process the Speculation-Rules header given a document document and a response response:
-
Optionally, return.
The user agent could ignore this header, for example, if it does not intend to consider speculation for document.
-
Let parsedList be the result of getting a structured field value given `
Speculation-Rules
` and "list
" from response’s header list. -
If parsedList is null, then return.
-
Let baseUrl be document’s document base URL.
-
For each item of parsedList:
-
Let parsedURL be the result of parsing item with baseUrl.
-
If parsedURL is failure, then continue.
-
Let pendingResource be a pending external speculation rule resource with URL parsedURL and controller null.
-
Append pendingResource to document’s list of pending external speculation rule resources.
-
Process pending external speculation rule resources given document.
In create and initialize a Document
object, before the step
Return document.
add the following step
Process the Speculation-Rules header given document and navigationParams’s response.
1.5. External speculation rule sets
To process pending external speculation rule resources given a document document:
-
Let pendingResources be document’s list of pending external speculation rule resources.
-
For each pendingResource of pendingResources:
-
Optionally, cancel and discard pendingResource given document, then continue.
-
If pendingResource’s controller is not null, then continue.
-
Optionally, fetch pendingResource given document.
The user agent schedules the fetch of external speculation rules at its discretion. That is, if it skips the fetch during this call of process pending external speculation rule resources, it might do the fetch during a later call.
-
To fetch a pending external speculation rule resource pendingResource given a document document:
-
Let pendingResources be document’s list of pending external speculation rule resources.
-
Assert: pendingResource’s controller is null.
-
Let settingsObject be document’s relevant settings object.
-
Let requestURL be pendingResource’s URL.
-
Let request be a new request whose URL is requestURL, client is settingsObject, mode is "
cors
", and destination is "speculationrules
". -
Let controller be the result of fetching given request with processResponseConsumeBody set to the following steps given response response and null, failure, or a byte sequence body:
-
Remove pendingResource from pendingResources.
-
If any of the following conditions are true, abort these steps:
-
body is null.
-
body is failure.
-
The result of extracting a MIME type from response’s header list does not have an essence of "
application/speculationrules+json
".
-
-
Otherwise, let text be the result of UTF-8 decoding body.
-
Let ruleSet be the result of parsing speculation rules given text, document and response’s URL.
-
If ruleSet is null, abort these steps.
User agents are encouraged to report failures of the previous steps.
-
Append ruleSet to document’s list of speculation rule sets.
-
-
Set pendingResource’s controller to controller.
To cancel and discard a pending external speculation rule resource pendingResource given a document document:
-
Let pendingResources be document’s list of pending external speculation rule resources.
-
Let controller be pendingResource’s controller.
-
If controller is not null, abort controller.
-
Remove pendingResource from pendingResources.
1.6. 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, document and baseURL.
-
If rule is null, then continue.
-
If rule’s target navigable name hint is not 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, document, 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
", "where
", "requires
", "target_hint
","referrer_policy
", "relative_to
", "eagerness
", and "expects_no_vary_search
" then return null. -
Let source be null.
-
If input["
source
"] exists, then:-
Set source to input["
source
"].
-
-
Otherwise, if input["
urls
"] exists and input["where
"] does not exist, then:-
Set source to "
list
".
-
-
Otherwise, if input["
where
"] exists and input["urls
"] does not exist, then:-
Set source to "
document
".
-
-
If source is neither the string "
list
" nor the string "document
", then return null. -
Let urls be an empty list.
-
Let predicate be null.
-
If source is "
list
":-
If input["
where
"] exists, then return null. -
If input["
urls
"] does not exist, is not a list, or has any element which is not a string, then return null. -
If input["
relative_to
"] exists:-
Let relativeTo be input["
relative_to
"]. -
If relativeTo is neither the string "
ruleset
" nor the string "document
", then return null. -
If relativeTo is "
document
", then set baseURL to the document’s document base URL.
-
-
For each urlString of input["
urls
"]:
-
-
If source is "
document
":-
If input["
urls
"] exists, then return null. -
If input["
relative_to
"] exists, then return null. -
If input["
where
"] does not exist, then set predicate to a document rule conjunction whose clauses is an empty list.Such a predicate will match all links.
-
Otherwise, set predicate to the result of parsing a document rule predicate given input["
where
"], document and baseURL. -
If predicate is null, then return null.
-
-
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
"]: -
Let targetHint be null.
-
If input["
target_hint
"] exists:-
If input["
target_hint
"] is not a valid navigable target name or keyword, then return null. -
Set targetHint to input["
target_hint
"].
-
-
Let referrerPolicy be the empty string.
-
If input["
referrer_policy
"] exists:-
If input["
referrer_policy
"] is not a referrer policy, then return null. -
Set referrerPolicy to input["
referrer_policy
"].
-
-
Let eagerness be "
immediate
" if source is "list
", and "conservative
" otherwise. -
If input["
eagerness
"] exists:-
If input["
eagerness
"] is not one of the valid eagerness strings, then return null. -
Set eagerness to input["
eagerness
"].
-
-
Let noVarySearchHint be the default URL search variance.
-
If input["
expects_no_vary_search
"] exists:-
If input["
expects_no_vary_search
"] is not a string, then return null. -
Set noVarySearchHint to the result of obtaining a URL search variance given input["
expects_no_vary_search
"].
-
-
Return a speculation rule with
- URLs
-
urls
- predicate
-
predicate
- requirements
-
requirements
- target navigable name hint
-
targetHint
- referrer policy
-
referrerPolicy
- eagerness
-
eagerness
- No-Vary-Search hint
-
noVarySearchHint
-
If input is not a map, then return null.
-
If input does not contain exactly one of "
and
", "or
", "not
", "href_matches
" and "selector_matches
", then return null. Otherwise, let predicateType be that key.This makes sure it is unambiguous what type of predicate is being used.
-
If predicateType is "
and
" or "or
", then:-
If input has any key other than predicateType, then return null.
This, and other similar checks below, make sure that unexpected extra options cause the predicate to be invalid.
-
Let rawClauses be the input[predicateType].
-
If rawClauses is not a list, then return null.
-
Let clauses be an empty list.
-
For each rawClause of rawClauses:
-
Let clause be the result of parsing a document rule predicate given rawClause, document and baseURL.
-
If clause is null, then return null.
-
Append clause to clauses.
-
-
If predicateType is "
and
", then return a document rule conjunction whose clauses is clauses. -
If predicateType is "
or
", then return a document rule disjunction whose clauses is clauses.
-
-
If predicateType is "
not
", then:-
If input has any key other than "
not
", then return null. -
Let rawClause be the input[predicateType].
-
Let clause be the result of parsing a document rule predicate given rawClause, document and baseURL.
-
If clause is null, then return null.
-
Return a document rule negation whose clause is clause.
-
-
If predicateType is "
href_matches
":-
If input has any key other than "
href_matches
" and "relative_to
", then return null. -
If input["
relative_to
"] exists, then:-
Let relativeTo be input["
relative_to
"]. -
If relativeTo is neither the string "
ruleset
" nor the string "document
", then return null. -
If relativeTo is "
document
", set baseURL to the document’s document base URL.
-
-
Let rawPatterns be input["
href_matches
"]. -
If rawPatterns is not a list, then set rawPatterns to « rawPatterns ».
-
Let patterns be an empty list.
-
For each rawPattern of rawPatterns:
-
Let pattern be the result of building a URL pattern from an Infra value rawPattern given baseURL. If this step throws, catch the exception and return null.
-
Append pattern to patterns.
-
-
Return a document rule URL pattern predicate whose patterns is patterns.
-
-
If predicateType is "
selector_matches
":-
If input has any key other than "
selector_matches
", then return null. -
Let rawSelectors be input["
selector_matches
"]. -
If rawSelectors is not a list, then set rawSelectors to « rawSelectors ».
-
Let selectors be an empty list.
-
For each rawSelector of selectors:
-
If rawSelector is not a string, then return null.
-
Parse a selector from rawSelector. If the result is failure, then return null. Otherwise, let selector be the result.
-
Append selector to selectors.
-
-
Return a document rule CSS selector predicate whose selectors is selectors.
-
1.7. Processing model
A document has a list of speculation rule sets, which is an initially empty list.
A document has a list of pending external speculation rule resources, which is an initially empty list of pending external speculation rule resources.
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.
The user agent might still consider speculation when there are rule sets that have not been loaded yet.
The user agent may also queue a global task on the networking task source with document’s relevant global object to process pending external speculation rule resources given document.
A prefetch candidate is a struct with the following items:
-
URL, a URL
-
anonymization policy, a prefetch IP anonymization policy
-
referrer policy, a referrer policy
-
eagerness, one of the valid eagerness strings
-
No-Vary-Search hint, a URL search variance
A prerender candidate is a struct with the following items:
-
URL, a URL
-
target navigable name hint, a valid navigable target name or keyword or null
-
referrer policy, a referrer policy
-
eagerness, one of the valid eagerness strings
-
No-Vary-Search hint, a URL search variance
-
prefetchRecord’s label is "
speculation-rules
" -
prefetchRecord’s state is not "
canceled
" -
prefetchRecord matches a URL given prefetchCandidate’s URL
-
prefetchRecord’s anonymization policy equals prefetchCandidate’s anonymization policy
Document
document and document rule predicate predicate:
-
Let links be an empty list.
-
For each shadow-including descendant descendant of document, in shadow-including tree order:
-
If descendant is not an
a
with anhref
attribute orarea
element with anhref
attribute, continue.This corresponds to the elements which match :any-link pseudo-class, or which appear in thelinks
collection. -
If descendant is not being rendered or is part of skipped contents, continue.
Such links, though present in the document, aren’t available for the user to interact with and are unlikely to be good candidates. In addition, they might not have their style or layout computed, which might make CSS selector matching less efficient in user agents which skip some or all of that work for these elements. -
Let url be descendant’s url.
-
If url is null, or its scheme is not an HTTP(S) scheme, continue.
-
If predicate matches descendant, then append descendant to links.
-
-
Return links.
a
element, an area
element, or null link:
-
If rule’s referrer policy is not the empty string, then return rule’s referrer policy.
-
If link is null, then return the empty string.
-
If link’s
rel
attribute includes thenoreferrer
keyword, then return "no-referrer
". -
Otherwise, return the current state of link’s
referrerpolicy
content attribute.The referrer policy computed based on link is intended to be equivalent to the referrer policy computation in following a hyperlink.
-
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:
-
⌛ Let referrerPolicy be the result of computing a speculative action referrer policy given rule and null.
-
⌛ Append a prefetch candidate with URL url, anonymization policy anonymizationPolicy, referrer policy referrerPolicy, eagerness rule’s eagerness, and No-Vary-Search hint rule’s No-Vary-Search hint to prefetchCandidates.
-
-
⌛ If rule’s predicate is not null, then:
-
⌛ Let links be the result of finding matching links given document and rule’s predicate.
-
⌛ For each link of links:
-
⌛ Let url be link’s url.
-
⌛ Let referrerPolicy be the result of computing a speculative action referrer policy given rule and link.
-
⌛ Append a prefetch candidate with URL url, anonymization policy anonymizationPolicy, referrer policy referrerPolicy, eagerness rule’s eagerness, and No-Vary-Search hint rule’s No-Vary-Search hint to prefetchCandidates.
-
-
-
-
⌛ For each rule of ruleSet’s prerender rules:
-
⌛ For each url of rule’s URLs:
-
⌛ Let referrerPolicy be the result of computing a speculative action referrer policy given rule and null.
-
⌛ Let prerenderCandidate be a new prerender candidate whose URL is url, target navigable name hint is rule’s target navigable name hint, referrer policy is referrerPolicy, eagerness is rule’s eagerness, and No-Vary-Search hint is rule’s No-Vary-Search hint.
-
⌛ Append prerenderCandidate to prerenderCandidates.
-
-
⌛ If rule’s predicate is not null, then:
-
⌛ Let links be the result of finding matching links given document and rule’s predicate.
-
⌛ For each link of links:
-
⌛ Let url be the link’s url.
-
⌛ Let target be rule’s target navigable name hint.
-
⌛ If target is null, set it to the result of getting an element’s target given link.
-
⌛ Let referrerPolicy be the result of computing a speculative action referrer policy given rule and link.
-
⌛ Let prerenderCandidate be a new prerender candidate whose URL is url, target navigable name hint is target, referrer policy is referrerPolicy, eagerness is rule’s eagerness, and No-Vary-Search hint is rule’s No-Vary-Search hint.
-
⌛ Append prerenderCandidate to prerenderCandidates.
-
-
-
-
-
⌛ For each prefetchRecord of document’s prefetch records:
-
End the synchronous section, continuing the remaining steps in parallel.
-
For each prefetchCandidate of prefetchCandidates:
-
The user agent may run the following steps:
-
Let prefetchRecord be a new prefetch record whose URL is prefetchCandidate’s URL, anonymization policy is prefetchCandidate’s anonymization policy, referrer policy is prefetchCandidate’s referrer policy, No-Vary-Search hint is prefetchCandidate’s No-Vary-Search hint, and label is "
speculation-rules
". -
Prefetch given document and prefetchRecord.
-
-
-
For each prerenderCandidate of prerenderCandidates:
-
The user agent may start referrer-initiated prerendering given prerenderCandidate’s URL, document, prerenderCandidate’s referrer policy, and prerenderCandidate’s No-Vary-Search hint.
The user agent can use prerenderCandidate’s target navigable name hint as a hint to their implementation of the start referrer-initiated prerendering algorithm. This hint indicates that the web developer expects the eventual activation of the created prerendering traversable to be in place of a particular predecessor traversable: the one that would be chosen by the invoking the rules for choosing a navigable given prerenderCandidate’s target navigable name hint and document’s node navigable.
This is just a hint. The target navigable name hint actually has no normative implications, after being parsed. It is still perfectly fine to activate in place of a different predecessor traversable that was not hinted at.
-
When selecting among prefetchCandidates and prerenderCandidates, user agents should consider their eagerness, in accordance with the following:
- "
immediate
" -
The author believes this is very likely to be worthwhile, and might also expect it to require significant lead time to complete. User agents should usually enact the candidate as soon as practical, subject only to considerations such as user preferences, device conditions, and resource limits.
- "
eager
" -
User agents should enact the candidate on even a slight suggestion that the user may navigate to this URL in the future. For instance, the user might have moved the cursor toward a link or hovered it, even momentarily, or paused scrolling when the link is one of the more prominent ones in the viewport. The author is seeking to capture as many navigations as possible, as early as possible.
- "
moderate
" -
User agents should enact the candidate if user behavior suggests the user may navigate to this URL in the near future. For instance, the user might have scrolled a link into the viewport and moved the cursor over it for some time. The author is seeking a balance between "
eager
" and "conservative
". - "
conservative
" -
User agents should enact the candidate only when the user is very likely to navigate to this URL at any moment. For instance, the user might have begun to interact with a link. The author is seeking to capture some of the benefits of speculative loading with a fairly small tradeoff of resources.
A user agent’s heuristics for enacting non-eager candidates could incorporate a No-Vary-Search hint. For example, a user hovering over a link whose URL and a candidate’s URL are equivalent modulo search variance given the candidate’s No-Vary-Search hint could indicate to the user agent that enacting it would be useful.
Notwithstanding the above, user agents should prioritize user preferences (express and implied, such as a low-data-usage mode) over eagerness expressed by the author.
We should also cancel speculated prerenders.
1.8. Document rule predicate matching
Element
el implementing the HTMLHyperlinkElementUtils
mixin if the following steps return true:
-
If predicate is a document rule conjunction, then:
-
If predicate is a document rule disjunction, then:
-
If predicate is a document rule negation, then:
-
If predicate is a document rule URL pattern predicate, then:
-
If predicate is a document rule CSS selector predicate, then:
-
For each selector of predicate’s selectors:
-
Match selector against el with the scoping root set to el’s root. If the result is true, return true.
During this step, user agents must apply the same privacy restrictions to the :visited pseudo-class as they would to other selector matching logic that could be observed by authors (e.g.,
querySelector(selectors)
).This is important to prevent this from opening an avenue for attackers to gather information about a user’s browsing history, e.g., by using a selector such as:root:has(.sensitive-site:visited) .report-sensitive-site
. See the Privacy Considerations section.
-
-
Return false.
-
-
Assert: This step is not reached.
2. Content Security Policy
Inline script use is restricted by [CSP], but there are cases where a developer doesn’t want to permit general inline scripts, but wants to permit inline speculation rules. So, we make the following change that extends [CSP] to support a new source keyword for inline speculation rules.2.1. Directives
In Content Security Policy 3 § 2.3 Directives, we define several associated algorithms, and an inline check algorithm needs a patch to define how to choose the type argument.-
An inline check, which takes an
TheElement
, atype
string, a policy, and a source string as arguments, and is executed during Content Security Policy 3 § 4.2.3 Should element’s inline type behavior be blocked by Content Security Policy? and during Content Security Policy 3 § 4.2.4 Should navigation request of type be blocked by Content Security Policy? forjavascript:
requests. This algorithm returns "Allowed
" unless otherwise specified.type
string is set to "script speculationrules
" if theElement
isHTMLScriptElement
and thetype
attribute is "speculationrules
", or set to "script attribute
" for JavaScript event handlers. Otherwise, it is set to "script
".
2.2. Source Lists
In Content Security Policy 3 § 2.3.1 Source Lists, we change the following definition to have a new source,inline-speculation-rules
.
keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'" / "'strict-dynamic'" / "'unsafe-hashes'" / "'report-sample'" / "'unsafe-allow-redirects'" / "'wasm-unsafe-eval'" / "'inline-speculation-rules'"
2.3. Should element’s inline type behavior be blocked by Content Security Policy?
Also, we make a following change for a note in Content Security Policy 3 § 4.2.3 Should element’s inline type behavior be blocked by Content Security Policy?.
Note: The valid values for type
are "script
", "script attribute
",
"script speculationrules
",
"style
", and "style attribute
".
2.4. script-src
Also we make the following change for Content Security Policy 3 § 6.1.10 script-src.-
Inline
script
blocks MUST pass through Content Security Policy 3 § 4.2.3 Should element’s inline type behavior be blocked by Content Security Policy?. Their behavior will be blocked unless every policy allows inline script, either implicitly by not specifying ascript-src
(ordefault-src
) directive, or explicitly, by specifying "unsafe-inline
", a nonce-source or a hash-source that matches the inline block , or specifying "inline-speculation-rules
" on the type attribute being "speculationrules
" .
2.5. Does a source list allow all inline behavior for type?
The algorithm needs a patch to handle the "script speculationrules
" type.
-
For each expression of list:
-
If expression matches the
nonce-source
orhash-source
grammar, return "Does Not Allow
". -
If
type
is "script
", "script attribute
" or "navigation
" and expression matches the keyword-source "'strict-dynamic'
", return "Does Not Allow
".Note:
'strict-dynamic'
only applies to scripts, not other resource types. Usage is explained in more detail in Content Security Policy 3 § 8.2 Usage of "'strict-dynamic'". -
If
type
is "script speculationrules
" and expression matches the keyword-source "'inline-speculation-rules'
", setallow all inline
totrue
. -
If expression is an ASCII case-insensitive match for the
keyword-source
"'unsafe-inline'
", setallow all inline
totrue
.
-
2.6. Does element match source list for type and source?
The algorithm needs patches to handle the "script speculationrules
" type at the step 2 and 5.
-
If
type
is "script
", "script speculationrules
", or "style
", and Content Security Policy 3 § 6.7.3.1 Is element nonceable? returns "Nonceable
" when executed upon element:-
For each expression of list:
-
If expression matches the
nonce-source
grammar, and element has anonce
attribute whose value is expression’sbase64-value
part, return "Matches
".
-
Note: Nonces only apply to inline
script
and inlinestyle
, not to attributes of either element or tojavascript:
navigations. -
-
Let unsafe-hashes flag be
false
. -
For each expression of list:
-
If expression is an ASCII case-insensitive match for the
keyword-source
"'unsafe-hashes'
", set unsafe-hashes flag totrue
. Break out of the loop.
-
-
If
type
is "script
", "script speculationrules
", "style
", or unsafe-hashes flag istrue
:
2.7. Get the effective directive for request
In Content Security Policy 3 § 6.8.1 Get the effective directive for request, the switch on the request destination needs one additional case.
At present, requests can only be issued in the case of the `Speculation-Rules
` header, so CSP does not apply. If support is added for loading external rule sets via <script src>
, for which CSP would apply, then the CSP directive selection will need to distinguish this case, such as by the introduction of a new request initiator.
- "
speculationrules
" -
-
Return null.
-
3. Fetch
3.1. Destination
The string "speculationrules
" is added to the list of valid destinations and also to the list of enumerators in RequestDestination
.
4. Security considerations
4.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.
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 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 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.
4.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. It would, however, make it possible to cause prefetches of links in the document, and the existence of those prefetches could provide a vector for exfiltrating information about those links.
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 default-src
directive applies to prefetch requests arising from the rules.
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. Therefore, [CSP] does not apply to the loading of rule sets via the header.
4.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.
Similarly, processing non-speculation rules resources as speculation rules is unlikely because this specification requires implementations to validate that its MIME type has an essence of "application/speculationrules+json"
.
4.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.
4.5. Mixed content
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 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 is not permitted at all, even from environments which are not themselves secure contexts.
5. Privacy considerations
5.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 eagerness
-
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
5.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.
5.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-site URL) or in an isolated partition, so as to ensure that prefetching does not become a mechanism for bypassing the partitioning scheme.
The prefetch specification allows issuing HTTP requests which behave consistently with the partitioning scheme. If a navigation using its response would load a document in the same partition (approximately, the top-level site would not change), then partitioned state (e.g., cookies) can be sent, as they can with subresource requests and scripted fetches. If it would load a document in another partition, it would be inconsistent with the partitioning scheme to use partitioned state for the destination partition (since this would cross the boundary between partitions without a top-level navigation) and also inconsistent to use partitioned state within the originating partition (since this would result in the user seeing a document with different state than a non-prefetched navigation). Instead, a third, initially empty, partition is used for such requests. These requests therefore contain no partitioned state from either partition (though it may still be possible to fingerprint the user agent by other means).
However, the response to a prefetch request in an empty partition can only be used if:
-
the response declares that the resource can be used even if an ordinary navigation would have sent credentials; or
-
the destination partition contains no credentials which would have been included
Checking the latter requires examining the destination partition’s state. To avoid this being a workaround for the partitioning scheme, the prefetch must continue even if the existence of conflicting partitioned state will preclude it being used for navigation.
Redirects are possible between these two types of requests. A redirect from a same- to cross-partition URL could contain information derived from partitioned state in the originating partition; however, this is equivalent to the originating document fetching the same-partition URL itself and then issuing a request for the cross-partition URL. A redirect from a cross- to same-origin URL could carry state from the isolated partition, but since this partition has no prior state this does not enable tracking based on the user’s prior browsing activity on that site, and the document could construct the same state by issuing uncredentialed requests itself.
5.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.
5.5. Visited links
It is imperative that the features in this specification do not allow sites to determine which other web sites a user has visited in the past.
Because a document rule CSS selector predicate can use arbitrary CSS selectors, it is critical that browsers apply the same privacy mitigations (which may not be covered by a specification) to the :visited pseudo-class as in other cases where it could be used by an attacker to extract information about the user’s browsing history. The matching algorithm requires this behavior. For more information, see Privacy and the :visited selector.