← 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.

Source: Fetch Standard — navigation TAO check

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.

Source: Fetch Standard — navigation TAO check; whatwg/html PR #12513

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.

Source: Fetch Standard — navigation TAO check; WPT navigation-timing/redirect-tao.html (withheld-hop and non-destination cases)

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).

Source: whatwg/html PR #12513 (caller conditional); Fetch Standard — navigation TAO check; Chromium runtime_enabled_features.json5; chromestatus.com/feature/5078310347472896

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.

Source: WHATWG HTML — navigation timing entry creation; whatwg/html PR #12513

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

navigation TAO check — interim, from ChromeStatus (checked 2026-07-26)
Engine / runtimeSupportNotes
Chrome151Milestone listing: Enabled by default (desktop, Android, WebView per the feature detail); runtime feature stable at trunk
EdgeNot separately reportedNo Edge position recorded on ChromeStatus
FirefoxNo signalVendor signal recorded on the ChromeStatus entry
SafariRecorded positive signalA 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 record

Security 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