Cookies

Cookie security in 5 minutes: Secure, HttpOnly, SameSite

Why cookies are worth protecting

When a user logs in, your server usually hands the browser a session cookie. From then on, that cookie is the user — every request carries it as proof of who they are. Which means if an attacker gets the cookie, they are logged in as that user, no password required. Three small attributes decide how well that cookie is guarded. None of them require new infrastructure; they are flags you set when the cookie is created.

HttpOnly: hide it from scripts

By default, JavaScript running on your page can read your cookies via document.cookie. That is fine until an attacker injects a script (cross-site scripting) — now their script can read the session cookie and send it to themselves. The HttpOnly flag tells the browser to keep the cookie out of JavaScript's reach entirely, so even a successful script injection cannot steal it. Every session cookie should have it; scripts never have a legitimate reason to read a session token.

Secure: HTTPS only

The Secure flag tells the browser to send the cookie only over encrypted HTTPS connections, never plain HTTP. Without it, a single accidental http:// request can carry the session cookie in the clear, where anyone on the network can grab it. With HTTPS everywhere this should be automatic — but only if you actually set the flag.

SameSite: control cross-site sending

SameSite decides whether the cookie is attached to requests that originate from other sites. This is the defense against cross-site request forgery, where a malicious page quietly makes a request to your site using the victim's logged-in cookie. The values:

  • Strict — the cookie is never sent on cross-site requests. Most protective, but can log users out when they arrive from external links.
  • Lax — sent on top-level navigations (clicking a link to your site) but not on background cross-site requests. A sensible default for most session cookies.
  • None — sent on all cross-site requests, and therefore required to also be Secure. Only use it when you genuinely need cross-site cookies.

A safe default

For a typical session cookie: HttpOnly, Secure, and SameSite=Lax. That hides it from scripts, keeps it on HTTPS, and blocks the common CSRF pattern, while still letting users follow links into your site normally. Tighten to Strict for the most sensitive cookies if the user experience allows.

Check your cookies

The flags on your cookies are easy to get wrong and invisible from the page. An automated scan reads the cookies your site sets and flags any session cookie missing HttpOnly, Secure or SameSite. Scan your site and make sure your sessions are not up for grabs.

Related reading

FAQ

Do I need all three flags on every cookie?
On session and authentication cookies, yes — HttpOnly, Secure and SameSite together. For non-sensitive cookies the rules are looser, but there is rarely a downside to setting them, and session cookies are where it really matters.
What is the difference between SameSite Lax and Strict?
Strict never sends the cookie on any cross-site request, which is most secure but can log users out when they follow an external link to your site. Lax still sends it on top-level navigations, so it blocks the common CSRF pattern while keeping links working — a good default.
If I use HTTPS everywhere, is the Secure flag redundant?
No. A stray http:// request — an old link, a typo, a mixed-content asset — can still carry the cookie in the clear unless Secure is set. The flag guarantees the browser never sends it unencrypted.