Cookie Attributes Explained: HttpOnly, Secure, SameSite
HttpOnly, Secure, and SameSite are cookie attributes that block script access, force HTTPS, and limit cross-site sending. Here's what each one actually stops.
Cookie attributes are flags set alongside a cookie’s name and value that tell the browser how to handle it: whether JavaScript can read it, whether it should only travel over HTTPS, and whether it should be sent on requests originating from other sites. HttpOnly, Secure, and SameSite are the three that matter most for security, and each one closes off a different attack, not the same one three times.
Setting them
A cookie with all three attributes looks like this in a Set-Cookie response header:
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/
There’s no default that makes all three safe automatically — omitting any one of them leaves that particular door open, regardless of what the others are set to.
HttpOnly: blocking JavaScript access
HttpOnly tells the browser not to expose the cookie to document.cookie or any other script-accessible API. The cookie still gets sent with HTTP requests as normal; it’s just invisible to client-side JavaScript.
This is aimed squarely at cross-site scripting: if an attacker manages to inject a script into your page, HttpOnly stops that script from reading the session cookie and exfiltrating it to another server. It doesn’t stop XSS from happening — it limits what a successful XSS attack can steal. Session and authentication cookies should essentially always be HttpOnly; there’s rarely a legitimate reason for client-side code to read a session identifier directly.
Secure: requiring HTTPS
Secure tells the browser to only send the cookie over an HTTPS connection, never plain HTTP. Without it, a cookie set on a secure page could still leak over an unencrypted connection — say, if a user follows an http:// link to the same domain, or a mixed-content resource on the page happens to load over HTTP — exposing it to anyone positioned to intercept unencrypted traffic on the network. Combined with HSTS, which tells the browser to never attempt an HTTP connection to your domain at all, Secure closes a gap that HSTS alone doesn’t fully cover for cookies set before HSTS takes effect. There’s essentially no modern reason to omit Secure on any cookie that matters, given that plain HTTP is now the exception rather than the norm — see HTTPS explained for why.
SameSite: limiting cross-site sending
SameSite is the newest and most nuanced of the three. It controls whether a cookie is sent on requests that originate from a different site than the one the cookie belongs to — the classic scenario being a form or image tag on evil.example that triggers a request to your-bank.example, carrying your session cookie along with it. That’s the mechanism behind CSRF attacks: the cookie proves you’re logged in, and the browser sends it regardless of which site initiated the request, unless SameSite says otherwise.
Three values, each a different tradeoff:
Strict— the cookie is never sent on cross-site requests, including a user clicking a link from an external site to yours. Most secure, but can break normal navigation-based flows (e.g., a user follows a link from an email into an app and appears logged out).Lax— the cookie is sent on top-level navigations (clicking a link) but not on cross-site subresource requests like images, iframes, or background fetches, and not on cross-site form submissions. This is the modern browser default whenSameSiteis unset, and it blocks the most common CSRF pattern while keeping normal navigation working.None— the cookie is sent on all cross-site requests, same as historical behavior with noSameSitesupport at all. Browsers requireSecurealongsideSameSite=None, refusing to honor the combination without it. This is only appropriate for cookies that genuinely need cross-site use, such as third-party embedded widgets.
Cookie attributes at a glance
| Attribute | Blocks | Doesn’t block |
|---|---|---|
HttpOnly | JavaScript reading the cookie | The cookie being sent over HTTP, or cross-site |
Secure | Sending the cookie over plain HTTP | JavaScript access, or cross-site sending |
SameSite=Lax/Strict | Sending the cookie on cross-site requests | JavaScript access, or interception over HTTP |
They stack — a session cookie should generally carry all three (HttpOnly; Secure; SameSite=Lax at minimum) because each one addresses a distinct threat model.
Where this fits with modern auth
If your app issues a JWT for API authentication rather than a traditional server session, the same attributes still apply if you store that token in a cookie rather than in client-side storage — and storing it in an HttpOnly cookie is generally safer than localStorage, which is fully readable by any script running on the page. Frameworks handling OAuth or OIDC flows, and increasingly passkey-based logins, still typically fall back to a cookie to maintain the resulting session, so these attributes remain relevant even as the initial login mechanism changes.
The takeaway
HttpOnly, Secure, and SameSite each stop a different attack: script-based theft, plaintext interception, and cross-site request forgery, respectively. None of them substitutes for the others, and a cookie missing any one of them is missing that specific protection regardless of what’s set elsewhere. For session and authentication cookies, set all three — HttpOnly, Secure, and at minimum SameSite=Lax — and reserve SameSite=None for the narrow case of cookies that genuinely need cross-site delivery.
Keep reading
Chisato · · 5 min read What Is Session Fixation?
Session fixation tricks a victim into using an attacker-known session ID, so logging in hands the attacker an authenticated session too.
Chisato · · 4 min read What Is IDOR? Insecure Direct Object References Explained
IDOR is an access control flaw where an app trusts a user-supplied ID to fetch a record without checking the requester actually owns it.
Chisato · · 4 min read The OAuth PKCE Flow Explained
PKCE hardens the OAuth authorization code flow against interception, and is now recommended for every client type, not just mobile and single-page apps.