SameSite Cookies, In Depth

On this page
  1. Strict, Lax, or None?
  2. What did the Lax-by-default change do?
  3. Where SameSite falls short

The SameSite cookie attribute controls whether a cookie is sent on cross-site requests, making it a frontline defense against CSRF. Its three values trade off security against usability, and a browser default change made Lax the baseline for most cookies. Understanding the distinctions is key to both securing and not accidentally breaking your app.

Strict, Lax, or None?#

ValueSent cross-site?Trade-off
StrictNeverMost secure; can log users out via external links
LaxOnly top-level GET navigationsBalanced; the modern default
NoneAlways (requires Secure)For legitimate cross-site cookies (e.g. embeds)

Strict is ideal for the most sensitive cookies where you never want cross-site delivery. Lax — now applied by default when no attribute is set — blocks the classic cross-site POST while still letting a user who clicks a link to your site arrive logged in. None must be paired with Secure and is for cookies that genuinely need to travel cross-site.

What did the Lax-by-default change do?#

Browsers now treat cookies with no SameSite attribute as Lax. This retroactively protected a huge number of sites from basic CSRF — but it also means a cookie that truly needs cross-site use must now explicitly declare SameSite=None; Secure, or it silently stops working in embedded contexts.

Where SameSite falls short#

SameSite is powerful but not a complete CSRF solution:

  • Some GET-based state changes can still be triggered.
  • Subdomains are same-site, so it does not isolate evil.example.com from app.example.com.
  • Older browsers may ignore it.

SameSite is the modern core of cookie security and CSRF defense. More at the Web Security hub.

Frequently asked questions#

What is the difference between SameSite Strict, Lax, and None?

Strict never sends the cookie on any cross-site request, even top-level navigation — most secure, but it can log users out when arriving from external links. Lax sends it only on top-level GET navigations, a balance now used as the browser default. None sends it on all cross-site requests but requires the Secure attribute.

Does SameSite fully replace CSRF tokens?

Not entirely. SameSite=Lax blocks the classic cross-site POST, covering many cases, but gaps remain: some GET-based state changes, complex subdomain or multi-site setups, and older browsers. Treat SameSite as a strong default layer and add anti-CSRF tokens for sensitive state-changing actions.

Sources & further reading