Missing SameSite Cookie Attribute
Updated July 6, 2026
4 min read
A missing SameSite cookie attribute means a cookie is set without a SameSite flag in its Set-Cookie response header, so the browser may attach it to cross-site requests. That behavior is what CSRF (cross-site request forgery) attacks rely on, which is why scanners and auditors flag session cookies that don't set it explicitly.
What is the SameSite cookie attribute?
SameSite is an attribute you add to a cookie in the Set-Cookie response header. It tells the browser whether that cookie should be sent along with requests that originate from a different site — for example, when another domain's page submits a form to yours, embeds your image, or links to your endpoint. It takes one of three values:
Strict— the cookie is never sent on any cross-site request, including top-level navigations from external links.Lax— the cookie is withheld on cross-site sub-requests (form POSTs, iframes, fetch/XHR) but still sent on top-levelGETnavigations, like clicking a link to your site.None— the cookie is sent on all cross-site requests. This value must be paired with theSecureattribute, or the browser rejects the cookie outright.
Modern Chromium and Firefox now treat a cookie with no SameSite attribute as SameSite=Lax by default. That helps, but relying on the default is still flagged as a finding: the behavior is inconsistent across older browsers and other clients, and it signals that cross-site protection was never set deliberately. Setting the attribute explicitly removes the ambiguity.
Why it's a risk / how it's exploited
The reason SameSite exists is to blunt CSRF. In a CSRF attack, a victim who is logged in to your site visits an attacker's page. That page silently fires a request at your application — a form submission, an image tag pointing at a state-changing URL, an auto-submitting form. Because the victim's browser automatically attaches their session cookie to any request bound for your domain, the request arrives fully authenticated, and your server executes it as if the user meant to.
Concrete scenario: your app has a "change email" endpoint that trusts the session cookie. An attacker hosts a page with a hidden form that POSTs a new email address to that endpoint and auto-submits it on load. A logged-in victim who opens the attacker's link has their account email quietly changed — the first step to a full account takeover via password reset. No stolen credentials, no XSS, just the browser doing what it's told.
With SameSite=Lax or Strict, the browser refuses to attach the session cookie to that cross-site POST, so the forged request lands unauthenticated and fails. A cookie left without the attribute — especially on older clients that don't apply the Lax default — leaves that door open.
How to detect it
Inspect the Set-Cookie response header and check whether a SameSite= attribute is present alongside Secure and HttpOnly:
curl -sI https://example.com | grep -i set-cookie
Look at each cookie line. A well-configured session cookie looks like Set-Cookie: sessionid=...; Path=/; Secure; HttpOnly; SameSite=Lax. If the SameSite= token is absent, the cookie is relying on the browser default. If you see SameSite=None without Secure, that's a separate misconfiguration — the browser will drop the cookie.
You can also open your browser DevTools → Application → Cookies and read the SameSite column per cookie. To check this alongside your other response headers in one pass, run the security headers checker. For the full picture across every page and cookie your app sets, a website vulnerability scan flags missing cookie attributes together with the rest of your OWASP Top 10 exposure.
How to fix it
Set the attribute where the cookie is created — at the application/framework level — not just at the edge. For session cookies, the safe combination is SameSite=Lax plus Secure plus HttpOnly. Lax is the right default for sessions because it still allows the cookie on ordinary inbound link clicks (top-level GET navigation), so users following a link into your site stay logged in, while cross-site POSTs are blocked. Use Strict only where you can accept that following an external link into the app won't carry the session (it can appear to log users out). Use SameSite=None; Secure only for cookies that genuinely must work in a cross-site context, such as embedded third-party widgets.
Most frameworks expose this on the cookie/session config directly (for example, cookie: { sameSite: 'lax', secure: true, httpOnly: true }). As a proxy-level backstop when you can't touch the app:
nginx (1.19.3+):
proxy_cookie_flags ~ samesite=lax secure httponly;
Apache (mod_headers) — use edit* so the rewrite applies to every Set-Cookie header, not just the first:
Header edit* Set-Cookie ^(.*)$ "$1; SameSite=Lax; Secure"
After deploying, re-run the curl -sI ... | grep -i set-cookie check and confirm every session cookie now shows SameSite=Lax; Secure; HttpOnly.
FAQ
Isn't the browser's Lax-by-default enough?
It helps modern browsers, but it's inconsistent on older clients and embedded contexts, and auditors still flag cookies that don't set the attribute explicitly. Setting SameSite=Lax yourself makes the behavior predictable everywhere.
Does SameSite replace CSRF tokens?
No. SameSite=Lax/Strict is a strong defense-in-depth layer, but keep server-side anti-CSRF tokens too — some request paths and legacy clients can still slip through, so treat SameSite as one control among several.
Not sure which of your cookies ship without a SameSite flag? Run a free website vulnerability scan to check your cookie attributes and the rest of your web attack surface in one pass.
