Article

The SameSite Cookie Attribute: Lax, Strict and None

The SameSite cookie attribute controls whether a cookie is sent on cross-site requests, the core defence against CSRF. Set it to Lax or Strict; a missing SameSite is minor because browsers default to Lax, but SameSite=None without Secure is silently dropped.

By Paul Rudenko, Security ResearcherUpdated Jun 30, 20266 min read

The SameSite attribute controls whether a cookie is attached to requests that come from other sites. It is the primary defence against cross-site request forgery (CSRF). Set it explicitly to Lax (a sensible default) or Strict on your cookies. A missing SameSite is only a minor gap today, because modern browsers already default to Lax — but None without Secure is a real error.

For the site owner (plain English)

In plain terms, SameSite controls whether your cookie tags along when a request comes from another website — the mechanism behind a class of trick called cross-site request forgery. Here is the reassuring part: if a checker says your SameSite is simply missing, that is a minor housekeeping note, not an emergency. Modern browsers already apply a safe default on your behalf, so you are largely covered even without setting it. It is still tidier to set it explicitly, and the simplest path is to ask your developer to set it toLax. The one thing that genuinely needs attention is the combinationNone without Secure, which browsers reject outright — but that is a specific misconfiguration, not the everyday “missing” case.

The three values

  • Strict — the cookie is never sent on any cross-site request, including when a user clicks a link from another site into yours. Strongest CSRF protection, but it can log users out when they follow an inbound link, so it suits sensitive apps (banking, admin).
  • Lax — the cookie is sent on top-level navigations (clicking a link) but not on cross-site sub-requests like images, iframes, or background fetch/form POSTs. This blocks the classic CSRF attack while keeping normal inbound links working. It is the right default for most session cookies.
  • None — the cookie is sent on all cross-site requests. Required for genuine cross-site use (embedded widgets, some SSO and payment flows), and the browser mandates Secure alongside it.

Why a missing SameSite is only a minor gap

Years ago, a cookie with no SameSite attribute was sent on every cross-site request, which left it open to CSRF. That changed: since 2020, Chrome and the other major browsers treat a cookie with no SameSite as SameSite=Lax by default. So an absent attribute now inherits the same protection as an explicit Lax for the common cases.

This is why an honest checker rates a missing SameSite as informational, not a medium or high vulnerability. It is still worth setting explicitly — defaults vary at the edges and being explicit is clearer — but it does not carry the same urgency as a session cookie missing Secure or HttpOnly. Tools that flag it as a serious issue are inflating the risk.

SameSite=None must be paired with Secure

The one genuine error in this area is SameSite=None without Secure. Browsers refuse to store a cross-site cookie that isn't marked Secure, so the cookie is silently dropped and whatever depended on it quietly breaks. If you truly need a cross-site cookie, always write both together:

Set-Cookie: sid=<token>; SameSite=None; Secure; HttpOnly; Path=/

And before reaching for None, ask whether you really need cross-site sending — most session cookies don't, and Lax is both safer and simpler.

How to set SameSite

# Raw header — the recommended default for a session cookie
Set-Cookie: sid=<token>; SameSite=Lax; Secure; HttpOnly; Path=/
// Express
res.cookie("sid", token, { sameSite: "lax", secure: true, httpOnly: true });

# Django settings.py
SESSION_COOKIE_SAMESITE = "Lax"
CSRF_COOKIE_SAMESITE = "Lax"

# Rails
Rails.application.config.session_store :cookie_store, key: "_app_session", same_site: :lax

// PHP
setcookie("sid", $token, ["samesite" => "Lax", "secure" => true, "httponly" => true]);

SameSite is a strong layer, but it is not a complete CSRF solution by itself — keep your anti-CSRF tokens for state-changing requests, especially if you must support SameSite=None anywhere. SameSite reduces the attack surface; tokens close the remaining gap.

Check your cookies' SameSite settings — free and passive.

Run the cookie checker

See the cookie security guide for the full picture, and pair this with Secure and HttpOnly.

Frequently asked questions

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

They differ in when the cookie is sent on cross-site requests. Strict never sends the cookie on any cross-site request, including when a user clicks a link from another site into yours — strongest protection, but it can log users out on inbound links, so it suits sensitive apps like banking or admin panels. Lax sends the cookie on top-level navigations (clicking a link) but not on cross-site sub-requests like images, iframes or background POSTs, which blocks the classic CSRF attack while keeping normal links working — it's the right default for most session cookies, e.g. Set-Cookie: sid=<token>; SameSite=Lax; Secure; HttpOnly; Path=/. None sends the cookie on all cross-site requests and is required for genuine cross-site use like embedded widgets or some SSO and payment flows, but the browser then mandates the Secure flag too. Reach for None only when you truly need it.

Is a missing SameSite attribute dangerous?

Not really, anymore. Years ago a cookie with no SameSite was sent on every cross-site request, which left it open to CSRF, but that changed: since 2020 all major browsers treat a cookie with no SameSite attribute as SameSite=Lax by default, so an absent attribute already gets Lax-level CSRF protection in the common case. That makes a missing SameSite a minor hardening gap rather than an active vulnerability — worth setting explicitly for clarity, because defaults can differ at the edges between browsers, but far less urgent than a session cookie missing Secure or HttpOnly, both of which are genuinely exploitable. An honest security check grades a bare missing SameSite as informational. The exception that does matter is SameSite=None without Secure, which browsers drop entirely — that one is a real bug to fix.

Does SameSite replace CSRF tokens?

No. SameSite=Lax or Strict is a strong, broad layer that blocks most cross-site request forgery automatically, but it isn't a complete solution on its own. Browser support and edge-case behaviour vary — older or embedded browsers may not enforce it consistently — and any cookie you deliberately set with SameSite=None is fully exposed to cross-site requests again, reopening the CSRF surface you were trying to close. Keep anti-CSRF tokens for state-changing requests (POST, PUT, DELETE) as defence in depth: the synchroniser-token or double-submit pattern still catches forged requests that slip past SameSite. Think of it as layered defence — SameSite shrinks the attack surface for free at the browser level, and the token closes the remaining gap on the requests that actually change state.

Related guides

See your whole external attack surface

One page is a start. The full external scan covers TLS, headers, DNS, exposed files, open services and known-exploited CVEs across your whole domain.

See the full scan →