Technical Publication

3. SameSite Cookies

The Browser Security Model Keeps Evolving Because Applications Keep Violating User Intent

SameSite doesn't fix a bug in cookies. It overrides a default that was never wrong on its own terms — only wrong for how the web ended up using it — and nobody but the browser vendor was ever positioned to make that call.

The SameSite attribute is a piece of metadata a server can attach to a cookie, telling the browser under what conditions that cookie should be included in a request. Set to Strict, the cookie is only sent on requests that originate from the same site the cookie belongs to — navigating from another site, or having another site trigger a request, won't include it. Set to Lax, the cookie is withheld on most cross-site requests but still sent on top-level navigations (clicking a link that takes you to the site), which is the compromise that keeps normal browsing — following a link to a site you're logged into — from silently logging you out. Set to None (which requires the cookie also be marked Secure, HTTPS-only), the cookie behaves the old way: attached to virtually any request to its domain, regardless of where that request originated.

That third option — None — is what cookies did by default, unconditionally, for the entire first few decades of their existence, because the original cookie specification had no concept of "which site initiated this request" at all. A cookie was scoped to a domain and a path. It said nothing about context. When a browser decided whether to attach a cookie to an outgoing request, the only question it asked was "does this request's destination match this cookie's domain scope" — never "is the page or script that triggered this request the same site the cookie belongs to." That second question wasn't omitted by oversight; the entire concept of tracking a request's originating site as something distinct from its destination site didn't yet exist as browser-level machinery when cookies were designed.

Why the Default Existed at All

It's worth resisting the temptation to read the original default as an oversight, because doing so misses what's actually interesting about this case. Cookies were introduced into Netscape Navigator in 1994 to solve a narrow, practical problem: HTTP has no built-in notion of a session, and a shopping cart, a login, or any other piece of continuity across multiple requests needed somewhere to live between them. A cookie scoped to a domain and attached to every request to that domain was a complete, working solution to that specific problem, and it shipped at a moment when the web's dominant interaction pattern — a person visiting one site at a time, largely in isolation from every other site — didn't expose "which page triggered this request" as a meaningful question. Nobody omitted a same-site check because they hadn't thought about security. The concept the check would need to reference — a request having a distinct, trackable originating context distinct from its destination — wasn't yet a thing browsers modeled internally, because nothing about how the web was used yet required them to.

What Changed, and What SameSite Actually Fixes

The SameSite attribute exists to retrofit that missing distinction, and it's most legible as a direct mitigation for the same mechanism the previous essay covers: cross-site request forgery relies entirely on the browser attaching credentials to a request regardless of who triggered it. A cookie marked Lax or Strict simply isn't available to be attached on most of the request patterns CSRF depends on — a hidden auto-submitting form on an attacker's page, a background fetch call, an <img> tag pointed at a state-changing endpoint. The credential the forged request needed just isn't there anymore, which closes the gap at the point where it actually lives (the browser's attach-or-don't-attach decision) rather than downstream, at the server, trying to detect after the fact that a request without a legitimate token or matching origin header looks forged.

Chrome's move to treat cookies without an explicit SameSite attribute as Lax by default — rather than the historical None — is the detail that makes this essay's argument concrete rather than abstract. That change didn't require any application to opt in. It changed the default interpretation of a cookie an application had already deployed, for every application that hadn't explicitly specified otherwise, unilaterally, at the browser layer. An application built years earlier, whose author never heard of SameSite because it didn't exist yet, got its cookie behavior changed out from under it the moment users updated their browser — in almost every case toward safer behavior, but occasionally breaking legitimate cross-site flows (single sign-on redirects, payment provider iframes, cross-domain widgets) that genuinely needed the old default and now have to explicitly opt back in with SameSite=None; Secure.

Where Lax Isn't Enough, and Where Strict Breaks Things

The choice between Lax and Strict is a real tradeoff, not a strictly-better-strictly-worse ordering, and it's worth being specific about why an application would pick one over the other rather than defaulting to the strongest setting everywhere. Strict withholds a cookie even on a top-level navigation arriving from another site — meaning if a user is logged into a site and clicks a link to it from an external page, email client, or search results, the very first request of that navigation goes out without the session cookie, because from the browser's perspective it can't yet distinguish "the user is navigating here of their own accord" from "something on the referring page triggered this." The practical effect is that Strict session cookies can make a user appear logged out the moment they arrive via an external link, and log them back in (or require a fresh authentication step) only after that first request completes. For a banking application, that extra friction on an already-rare, already-sensitive cross-site entry point is usually an acceptable cost. For a content site people routinely reach by clicking search results or shared links, it would mean showing every incoming visitor a logged-out state on their very first page view — a broken experience for the common case, in exchange for protection against a comparatively narrow slice of additional risk that Lax doesn't already cover.

This is also where the interaction with authentication flows that inherently span origins becomes unavoidable rather than incidental. Single sign-on redirects, OAuth authorization code exchanges, and payment provider iframes all depend on a cookie being readable in a context that is, by definition, not same-site with the page the user started on — an identity provider's session cookie has to survive being redirected back to from the application that's relying on it. These flows are exactly the ones that break when a browser's default tightens, and exactly the ones an application has to deliberately mark SameSite=None; Secure to keep functioning, which is also, not coincidentally, exactly the configuration that reopens the ambient-credential-attachment behavior this whole essay is about. The safe default and the cross-site flows a modern web application actually needs to support are in genuine, structural tension — not because anyone designed either side carelessly, but because "let a credential travel across a site boundary safely" and "prevent credentials from traveling across site boundaries by default" are opposing requirements that show up in the same systems simultaneously, and SameSite's three-way Strict/Lax/None split exists specifically to let an application declare, cookie by cookie, which requirement wins for that particular piece of state.

Browser Vendors as a Lagging Proxy for Accumulated Harm

That's the shape worth naming, once, plainly: browser vendors changing a cookie default is a correction applied at the one layer that can unilaterally apply it to the entire installed base of the web at once — but it's a correction that only ever arrives after the harm from the old default has already accumulated across the industry for years, been documented, been exploited repeatedly, and become legible enough as a pattern that a vendor is willing to break some existing sites in order to fix the rest. No one owns "recalibrate what cookies do by default" on any faster loop than that. It isn't a standards committee revisiting cookie semantics on a schedule; it's a reactive move, made under the pressure of a body of exploited real-world harm large enough to justify the compatibility risk of changing a default the entire web had been depending on, one way or another, for decades.

This is worth resisting the urge to over-explain, because the cookie specification's actual history — RFC 2965, the eventual consolidation into RFC 6265, the incremental additions of Secure, HttpOnly, and finally SameSite across multiple browser-specific proposals before standardization — is a long story about protocol governance, and almost none of it is the point here. The point is narrower: the entity that ended up responsible for correcting an implicit default that had drifted from safe to harmful was neither the standards body that originally specified cookies (which had moved on) nor the millions of applications running on the old default (which had no mechanism for coordinated, simultaneous change) — it was whichever browser vendors had enough market share and enough documented harm in hand to justify making the call unilaterally. That's not a criticism of Chrome, Firefox, or Safari for stepping in. It's an observation that "step in" was left to them by default, because nobody else was positioned to.

The trust boundary here is the one between what a cookie's original scope was intended to mean and what browsers now have to assume it means given how the web actually uses cross-site requests — and today, that boundary is owned by browser vendors, reactively, years after the fact, because no earlier layer in the stack — not the cookie spec, not the applications setting cookies, not any standards process — was ever assigned to keep that meaning calibrated as it happened.