← Cross-origin redirect timing opt-in
v151 · fetch · algorithm reference
navigation TAO check
The fetch algorithm that decides, once a navigation's destination origin is known, whether every redirect in the chain allowed that origin to measure it. Success lets HTML expose the chain's redirect timing; failure keeps it zero.
Syntax
// Fetch Standard — perform a navigation TAO check,
// given a response and an origin destinationOrigin:
//
// For each taoValues of response's
// navigation timing allow values list:
// If taoValues contains "*", then continue.
// If taoValues contains destinationOrigin, serialized,
// then continue.
// Return failure.
// Return success.
Source: Fetch Standard — navigation TAO check
Inputs
The algorithm takes the navigation's final response (which carries the cloned navigation timing allow values list — one entry per redirect hop) and the navigation's destination origin. Each entry is a list of strings produced by get/decode/split of one redirect response's Timing-Allow-Origin header.
Outputs
Success or failure. Success requires every list entry to contain either * or the destination origin, serialized. Notable semantics of the wildcard, read straight from the steps: * succeeds regardless of credentials (there is no credentials branch, unlike CORS) and it need not be the sole member — a values list containing * among other origins still continues. HTML uses the result in its redirect-timing conditional: success (plus the referrer gate) sets the real redirect count and times; failure leaves them zero.
Errors
The algorithm has no exception paths — failure is a value, not a throw. The boundary cases, by construction: an empty values list (a hop that sent no header) contains neither * nor the destination, so it fails the chain; and the check iterates every entry — same-origin hops included whenever the chain contains any cross-origin redirect — so one unopting hop anywhere fails the whole chain.
Context
Caller: the HTML navigation steps, when creating the navigation timing entry — and only when the response's has cross-origin redirects flag is set (a purely same-origin chain skips the check entirely and always exposes). The HTML conditional additionally requires the request's client to be null or its referrer not no-referrer; that gate, like the check, engages only for cross-origin-including chains.
Sibling algorithm: the older TAO check (§4.11) for subresources, which opts in the requesting origin — a different direction with a different caller. Do not conflate the two.
Implementation: the exposure flag that this check feeds is plumbed through Chromium's document_loader.cc and read by the timing getters in performance_navigation_timing.cc. Availability: Chrome 151 per the milestone listing; runtime feature NavigationTimingRedirectTimingViaTAO (status stable at trunk).
Lifecycle
The check runs once per navigation, after the final response arrives and its cloned values list is complete, and its result is fixed into the navigation timing entry created at document commit. There is no re-evaluation: later script cannot change the outcome, and the entry's redirectCount /redirectStart /redirectEnd reflect it for the document's lifetime.
Examples
// Given destination origin "https://c.example" and the cloned list:
« « "https://c.example" », « "*" » » → success
« « "https://c.example" », « » » → failure (hop 2 sent no header)
« « "https://not-c.example" » » → failure (opted a different origin)
« « "*", "https://other.example" » » → success ("*" need not be sole member)
// WPT executable contract (navigation-timing/redirect-tao.html):
// [dest] → exposed (count 1)
// ["*"] → exposed (count 1)
// [dest, dest] → exposed (count 2)
// [non-dest] → hidden
// [null, dest] → hidden (every hop must opt in)
Source: Fetch Standard — navigation TAO check; WPT navigation-timing/redirect-tao.html
Compatibility
| Engine / runtime | Support | Notes |
|---|---|---|
| Chrome | 151 | Milestone listing: Enabled by default (desktop, Android, WebView per the feature detail); runtime feature stable at trunk |
| Edge | Not separately reported | No Edge position recorded on ChromeStatus |
| Firefox | No signal | Vendor signal recorded on the ChromeStatus entry |
| Safari | Recorded positive signal | A recorded signal, not an official WebKit standards position |
Internal algorithm, not BCD-tracked; feature signals per the ChromeStatus API feature record.
Source: ChromeStatus API feature recordSecurity and privacy
This algorithm is the enforcement point of the opt-in model: it is what prevents a destination from measuring any chain whose redirects did not all consent. The all-entries rule means consent cannot be partially given — a chain that mixes opted and unopted hops discloses nothing. The algorithm reads only the declared values and the destination origin; it exposes no list contents to script.
Source: Fetch Standard — navigation TAO check; whatwg/fetch PR #1931