Fetch Metadata Adds Request Context to Server-Side Policy
A server often sees the same authenticated cookie on requests created by very different browser actions. A form submitted from another site, a same-origin API call, an image load, and a top-level navigation can all reach the same host. Cookies alone do not describe that request context.
Fetch Metadata adds browser-generated request headers that describe where a request came from and how the browser intends to use the response. A server can incorporate those signals into an isolation policy before application logic handles a sensitive route.
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: imageThese headers do not authorize a principal. They provide context for a separate server-side decision.
The four core headers describe different dimensions
The Fetch Metadata request headers are Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, and Sec-Fetch-User.
Sec-Fetch-Site describes the relationship between the initiator and target. Its common values are same-origin, same-site, cross-site, and none. The none value covers requests without a requesting site, such as some direct user navigations.
Sec-Fetch-Mode reports the request mode, including values such as navigate, cors, no-cors, same-origin, and websocket.
Sec-Fetch-Dest describes the intended destination. Values such as document, image, script, and empty let a server distinguish a document navigation from a subresource or API-style fetch.
Sec-Fetch-User is present with ?1 when a navigation is associated with user activation. Its absence is not equivalent to a failed authentication check; it simply means that signal is not present for the request.
Because these names use the Sec- prefix, browser page scripts cannot freely set or modify them as ordinary request headers.
A policy starts with endpoint intent
A useful policy is based on what an endpoint is meant to accept. Consider an authenticated JSON route that is only called by same-origin application code. A cross-site image load has no legitimate reason to reach that route, even if the browser attaches cookies.
A compact rule can reject that mismatch:
if Sec-Fetch-Site == cross-site
and route is not explicitly cross-site:
rejectProduction rules usually need more detail. Public resources, federated login callbacks, webhook endpoints, CORS APIs, and top-level links can intentionally receive traffic from outside the site. A blanket rejection of every cross-site request would break valid flows.
The policy therefore belongs beside an endpoint inventory, not as an isolated middleware switch.
Same-site is not always the same trust boundary
same-site is broader than same-origin. Two sibling subdomains can be same-site while running software with different operators, deployment controls, or exposure.
An application that treats every same-site request as trusted effectively places those sibling origins inside one browser-facing trust boundary. That can be appropriate for tightly controlled infrastructure, but it should be a deliberate decision.
For sensitive routes, allowing same-origin and evaluating same-site separately creates a narrower default.
Navigations need their own rule
Cross-site navigation is normal web behavior. A user can click a link on one site and arrive at another. A policy that rejects all cross-site requests would block that basic path.
For routes intended to serve pages, a policy can distinguish a top-level navigation from a subresource request by combining metadata fields. For example, a GET request with Sec-Fetch-Mode: navigate and Sec-Fetch-Dest: document has a different purpose from a no-cors image request aimed at the same URL.
Method checks still matter. Treating every navigation as safe would be a mistake if an application performs state changes on GET. Safe HTTP semantics remain part of the boundary.
Missing headers require an explicit compatibility choice
Not every client is a browser that sends Fetch Metadata. Command-line clients, server-to-server integrations, older clients, and specialized user agents can omit the headers.
A deployment must define what omission means. One service may permit missing metadata only on documented machine endpoints. Another may allow it temporarily while measuring browser coverage. A high-risk browser-only route may choose a stricter fallback.
The important property is that absence is handled intentionally. Silently treating a missing header as same-origin converts a compatibility fallback into a trust grant.
Fetch Metadata complements CSRF controls
Fetch Metadata can reject many requests whose browser context conflicts with an endpoint’s intended use, including cross-site requests involved in CSRF patterns. It should not be treated as a replacement for every CSRF control.
Applications can still need SameSite cookie settings, anti-CSRF tokens, Origin or Referer validation, reauthentication for sensitive actions, and correct authorization. The exact set depends on the request model.
Fetch Metadata is especially useful as an additional server-side gate because the decision can happen before parsing a large request body or invoking sensitive application logic.
Cache behavior must match the policy
If a response can differ according to request metadata and a shared cache sits in front of the application, cache behavior deserves review. A cache that ignores the relevant request headers can reuse a response in a context the origin server would have treated differently.
Where responses vary on Fetch Metadata, the cache key or Vary behavior must match the deployment architecture. This is not a reason to add every metadata header to every response. It is a reason to align cache configuration with the fields that actually affect response selection.
Rollout works best in observation first
A new isolation rule can expose hidden integrations. Before enforcing rejection, log the metadata tuple, route, method, decision, and a bounded amount of diagnostic context. Do not log session secrets or full authorization credentials.
The observation period can reveal endpoints that legitimately accept cross-site navigations, CORS traffic, embedded resources, or non-browser clients. Those exceptions can then be made explicit.
After enforcement starts, rejected requests should remain observable. A sudden rise in denials can indicate an attack pattern, a client regression, or an incomplete route inventory; the status code alone cannot distinguish them.
Request context is a gate, not identity
Fetch Metadata gives the server browser-supplied context about a request. It does not prove which user is entitled to an object, whether a session is still valid, or whether a state transition is permitted.
That separation keeps the control precise. Authentication establishes identity. Authorization governs access. CSRF defenses protect state-changing browser requests. Fetch Metadata lets the server reject browser contexts that should never have reached a route in the first place.
A strong deployment keeps those roles separate, documents intentional cross-site paths, treats same-site as a conscious trust decision, and defines a safe fallback for clients that do not send the headers.