What do the HttpOnly, Secure, SameSite, Domain/Path, and Expires/Max-Age cookie attributes control, and how do they defend against attacks?
Whether you can harden a session cookie against XSS and CSRF.
HttpOnly: the cookie is invisible to JavaScript (document.cookie can't read it) — this is the primary defense against XSS stealing a session token; set it on all auth cookies. Secure: the cookie is only sent over HTTPS, preventing interception on plaintext connections. SameSite controls cross-site sending and is the main CSRF defense: Strict never sends the cookie on cross-site requests (safest, but breaks inbound links to logged-in pages); Lax (the modern default) sends it on top-level GET navigations but not on cross-site POSTs or subresource requests; None sends it always but REQUIRES Secure — used for legitimate third-party/embedded contexts. Domain scopes which hosts receive it (omit to keep it host-only; setting a parent domain shares it with subdomains); Path scopes it to a URL prefix. Expires (absolute date) / Max-Age (seconds) set lifetime — omit both for a session cookie that dies when the browser closes. Hardened session cookie: `Set-Cookie: sid=…; HttpOnly; Secure; SameSite=Lax; Path=/`. Note these are set by the SERVER via the Set-Cookie header; JS can only set non-HttpOnly cookies. Prefix names with __Host- to lock a cookie to Secure + host-only + Path=/ for extra hardening.
Configuring auth/session cookies: HttpOnly + Secure + SameSite is the baseline against XSS token theft and CSRF.
Set-Cookie: sid=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
HttpOnly → hidden from document.cookie (blocks XSS token theft)
Secure → HTTPS only (blocks interception)
SameSite → Strict | Lax | None (blocks CSRF; None requires Secure)
Domain/Path→ scope of who/where receives it
Max-Age/Expires → lifetime (omit both = session cookie)