Scanverra
Back to Articles
Security

Secure Cookie Configuration: SameSite, Secure, and HttpOnly Explained

·7 min read

Three attributes on a Set-Cookie header, each closing off a completely different kind of attack. Most teams get one of the three right and never revisit the other two - here's what each is actually for.

Secure: Stops Network Interception

Without the Secure flag, a browser will send the cookie over plain HTTP as readily as HTTPS. If a user ever lands on an http:// version of your site - an old bookmark, a typed URL without the protocol, a stray internal link - the cookie goes out in plaintext, readable by anyone positioned on the network path.

Securetells the browser to withhold the cookie entirely unless the connection is HTTPS. It doesn't encrypt the cookie's value - it just refuses to send it somewhere that isn't encrypted in the first place.

HttpOnly: Stops JavaScript (and XSS) From Reading It

A cookie without HttpOnly is readable via document.cookieby any JavaScript running on the page - including your own analytics snippet, a third-party widget, or, in the event of a cross-site scripting vulnerability anywhere on the site, an attacker's injected script.

HttpOnlyremoves the cookie from that API entirely - JavaScript simply can't see it, the browser still attaches it to requests automatically. This is why HttpOnly on a session cookie is one of the single highest-leverage security defaults available: it turns "one XSS bug" from "full session takeover" into "still bad, but not immediately account-compromising."

SameSite: Stops Cross-Site Requests From Carrying It

By default (in the absence of SameSite, historically), a browser attaches a site's cookies to requests regardless of which site initiated them - which is precisely the mechanism CSRF attacks depend on. SameSite restricts that:

  • Strict - the cookie is never sent on a cross-site request, including a user clicking into your site from an external link.
  • Lax - blocks cross-site POSTs (the main CSRF vector) while still sending the cookie on top-level navigation, so a user following a link into your site stays logged in.
  • None - the cookie is sent on all cross-site requests; required for legitimate cross-site use cases (an embedded widget), but must be paired with Secure or modern browsers reject it outright.

Putting all three together on a typical session cookie:

Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/

The One Legitimate Exception

A double-submit CSRF token pattern requires client-side JavaScript to read a cookie's value and echo it back in a request header - that specific cookie has to skip HttpOnly by design. Every other cookie on the same site, especially the session/auth cookie, should still have it.

Why This Slips Through Review

None of the three missing flags causes a visible bug - the site works identically either way, until someone specifically tests for the missing protection. That's exactly why it's worth checking explicitly rather than assuming a framework default has it covered; not every cookie library ships with secure defaults enabled out of the box.

Find out which headers you're missing

Run a free security scan and get a plain-English breakdown of every header, cert, and exposed secret.

Run a free security scan