Skip to content

Attributes and SameSite

Cookie attributes are added after the name=value pair, separated by semicolons. They control lifetime, scope, transport security, and cross-site behaviour.

Set-Cookie: session=abc123; Max-Age=3600; Path=/; Secure; HttpOnly; SameSite=Strict

Only the name=value pair is required. Every attribute is optional, but omitting security-relevant attributes like SameSite and Secure leaves cookies vulnerable.

These two attributes control whether a cookie is a session cookie or a persistent cookie.

No Expires/Max-Age → session cookie. The browser deletes it when the tab/window session ends (browser close behaviour varies by browser and “restore session” settings).

Set-Cookie: pref=dark

Expires=<date> → persistent cookie, deleted at the given UTC date:

Set-Cookie: pref=dark; Expires=Thu, 01 Jan 2027 00:00:00 GMT

Max-Age=<seconds> → persistent cookie, deleted after this many seconds from now. This is preferred over Expires because it is relative and avoids clock-skew issues:

Set-Cookie: pref=dark; Max-Age=86400

Setting Max-Age=0 (or a negative value) deletes the cookie immediately.

Path restricts which request URLs the browser attaches the cookie to:

Set-Cookie: admin_token=xyz; Path=/admin

The browser only sends this cookie on requests to paths that begin with /admin. Requests to / or /app do not include it.

Default: if omitted, browsers use the path of the URL that set the cookie (often /).

Domain controls which hostnames receive the cookie:

Set-Cookie: pref=dark; Domain=.example.com

A leading dot (.example.com) means the cookie is sent to example.com and all its subdomains (api.example.com, www.example.com, etc.).

Without Domain, the cookie is sent only to the exact host that set it (no subdomains).

Secure instructs the browser to send the cookie only over HTTPS connections:

Set-Cookie: session=abc; Secure

Without Secure, the cookie is sent over plain HTTP, where it can be intercepted by network attackers (man-in-the-middle). All cookies containing sensitive data must have Secure.

HttpOnly is one of the most important security attributes. It prevents JavaScript from reading the cookie via document.cookie:

Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict

With HttpOnly, even if an attacker injects malicious JavaScript into your page (XSS), that script cannot steal the session cookie. The cookie is still sent automatically with HTTP requests — it just cannot be read or modified by JavaScript.

HttpOnly cookies can only be set by the server via the Set-Cookie header. Client-side document.cookie cannot set HttpOnly cookies.

SameSite controls when cookies are sent on cross-site requests, defending against CSRF (Cross-Site Request Forgery) attacks.

SameSite=Strict — cookie is sent only on same-site requests (navigations and requests that originate from your own site). Never sent on cross-site requests:

Set-Cookie: session=abc; SameSite=Strict

Best for session cookies — maximum CSRF protection.

SameSite=Lax (default in modern browsers) — cookie is sent on same-site requests AND on top-level navigations from other sites (e.g., clicking a link to your site from an email). Not sent on cross-site subresource requests (images, iframes, fetch):

Set-Cookie: pref=dark; SameSite=Lax

Good balance for most cookies.

SameSite=None; Secure — cookie is sent on all requests including cross-site. Must be paired with Secure or browsers reject it. Required for legitimate cross-site use cases (e.g., embedded widgets, third-party authentication):

Set-Cookie: analytics_id=abc; SameSite=None; Secure
Section titled “Recommended combination for session cookies”

For any cookie that authenticates a user or authorises an action, use all three security attributes:

Set-Cookie: session=abc123; Max-Age=3600; Path=/; Secure; HttpOnly; SameSite=Strict

This combination:

  • Sends the cookie only over HTTPS (Secure)
  • Blocks JavaScript access, preventing XSS theft (HttpOnly)
  • Prevents the cookie being sent on cross-site requests, blocking CSRF (SameSite=Strict)
OptionBenefitCost
HttpOnlyProtects a session token from XSS theft — JavaScript can never read that cookie at allClient-side JavaScript cannot read or update the value itself; only the server can
SameSite=StrictMaximum CSRF protection — the cookie is never sent on a cross-site requestBreaks flows that depend on the cookie during cross-site navigation, e.g. clicking an email link and still being logged in
SameSite=None; SecureSupports legitimate cross-site use cases, like embedded widgets or third-party authOpens the door for the cookie to be sent on every cross-site request, widening the CSRF surface without extra protections
  • Not setting SameSite/Secure at all — the cookie risks being sent over plain HTTP (no Secure) and is more exposed to CSRF if the browser or an old config doesn’t enforce a safe default.
  • Setting SameSite=None without pairing it with Secure — modern browsers reject the entire cookie outright, not just warn about it.
  • Storing an auth token in a cookie that isn’t HttpOnly — this defeats the main security purpose of using a cookie, since a script injected via XSS can read that token immediately.
What does Max-Age=0 do to a cookie?
Which attribute prevents JavaScript from reading a cookie via document.cookie?
What is the difference between SameSite=Strict and SameSite=Lax?
A cookie has SameSite=None. What other attribute is required for the browser to accept it?