Safe settings for a session cookie
Set a session cookie with Secure, HttpOnly and SameSite=Lax (or Strict), a __Host- name prefix, Path=/ and no Domain attribute. Together these keep it off plain HTTP and away from page scripts, leave it out of most cross-site requests and tie it to one host.
Each attribute addresses a different risk, and none of them replaces session checks on the server.
Set-Cookie: __Host-session=3f9a1c7e5b2d48e0a6c4; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=28800Secure and HttpOnly
Secure tells the browser to send the cookie only over HTTPS, so it never travels in clear text. Modern browsers also refuse to let an http:// page set a Secure cookie. Secure protects the cookie in transit only; it is still readable on the user's device.
HttpOnly hides the cookie from JavaScript, so document.cookie can't read it. That limits what cross-site scripting can steal, but an injected script can still send requests as the user and the browser will attach the cookie. Use HttpOnly for session and authentication cookies, and leave it off only for values your scripts need to read.
SameSite: Strict, Lax and None
SameSite controls whether the cookie is sent with requests that another site started. A site here means the scheme plus the registrable domain, so app.example.com and www.example.com are the same site even though they are different origins.
- Strict: never sent on cross-site requests, including a click on a link from another site. Visitors arriving from an email or a search result look signed out until their next request.
- Lax: sent on top-level navigation with safe methods such as GET, but not on cross-site POST requests or on subrequests such as images, iframes and fetch calls. It is a good default for session cookies.
- None: sent on every request, including cross-site ones. SameSite=None requires Secure, and browsers that enforce the rule reject the cookie without it. Third-party cookie restrictions may still block it.
When SameSite is missing
Without a SameSite attribute, behavior depends on the browser. Chromium-based browsers treat the cookie as Lax, while other browsers may still send it on cross-site requests. Set SameSite explicitly so you aren't relying on a default.
SameSite reduces cross-site request forgery but does not replace anti-CSRF tokens, because a compromised subdomain counts as the same site.
The __Host- and __Secure- prefixes
Cookie name prefixes make the browser enforce rules at the moment a cookie is set. They stop a plain-HTTP page, and with __Host- also a subdomain, from planting a cookie under that name for your host.
- __Secure-: the cookie must have the Secure attribute and be set from an HTTPS page.
- __Host-: the cookie must have Secure, be set from an HTTPS page, use Path=/ and have no Domain attribute. That locks it to the exact host that set it.
Domain and Path scope
Leaving out Domain creates a host-only cookie, sent only to the exact host that set it. Setting Domain=example.com widens the cookie to example.com and every subdomain, which is the opposite of what many people expect.
Set Domain only when several subdomains need the cookie. Every one of them, including any that run third-party or poorly maintained software, will then receive it and can overwrite it.
Path limits which URL paths the cookie is sent to, but it is no security boundary: pages on the same origin can reach cookies set for other paths. Keep applications that must not share cookies on separate hosts.