· 4 min read
How to Audit Cookie Security Flags
Manesh Jayawardhana
CIO & Co-founder
Set-Cookie: session=abc123; Path=/
That’s a session cookie with no protections at all. It can be read by any JavaScript on the page, sent over plain HTTP, and attached to requests originating from other sites. Three separate problems, three separate flags, and they defend against three different attacks.
Treating them as a checklist misses why they matter.
What each flag actually prevents
HttpOnly stops JavaScript reading the cookie via document.cookie.
Its value is specifically in limiting the damage from cross-site scripting. If an attacker manages to run script on your page — through a vulnerable dependency, an unsanitised input, a compromised third-party tag — HttpOnly means that script can’t simply read the session token and send it elsewhere. It doesn’t prevent XSS; it means one successful XSS doesn’t hand over every logged-in session.
Any cookie your own JavaScript never needs to read should have it, which is most session cookies.
Secure stops the cookie being sent over plain HTTP.
On an HTTPS-only site this sounds redundant. It isn’t: a single accidental plain-HTTP request — an old bookmark, a mistyped link, a hard-coded http:// in an email — sends the cookie in clear text before any redirect happens. The redirect fixes the page load; it doesn’t unsend the cookie.
SameSite controls whether the cookie is attached to requests originating from other sites.
This is the cross-site request forgery defence. With SameSite=Lax, a form on an attacker’s site submitting to your endpoint doesn’t carry the user’s session cookie, so the request isn’t authenticated. Strict goes further and also withholds it on ordinary navigation from other sites, which breaks inbound links into logged-in areas. None disables the protection and requires Secure.
Browsers now default to Lax when the attribute is absent, which closed a large hole — but relying on a default rather than declaring it means your behaviour depends on the browser.
| Flag | Prevents | Set it on |
|---|---|---|
| HttpOnly | Script reading the cookie | Anything JS doesn’t need |
| Secure | Transmission over HTTP | Everything |
| SameSite=Lax | Cross-site request forgery | Session cookies |
| SameSite=None | — requires Secure | Genuine cross-site use only |
The other attributes
Path and Domain control scope. A cookie set on .example.com is sent to every subdomain, including any you don’t fully control — a marketing subdomain on a third-party platform, for instance. Scope narrowly.
Max-Age and Expires control lifetime. A session cookie that persists for a year is a session that can be stolen for a year.
__Host- prefix is worth knowing: a cookie named with it must be Secure, must have no Domain attribute, and must have Path=/. Browsers enforce those constraints, which makes the prefix a self-documenting guarantee.
Common mistakes to avoid
- Setting
SameSite=Noneto fix an integration without also setting Secure, which browsers reject. - Using
Stricton the main session cookie, which logs users out when they arrive from an external link. - Scoping a session cookie to
.example.comwhen it’s only needed on one host. - Omitting HttpOnly because a script reads the cookie once, when the value could be delivered another way.
- Auditing the login cookie and ignoring the other eleven the site sets.
How to do it with Cookie Flag Auditor
The Cookie Flag Auditor checks the header in your browser.
- Paste the Set-Cookie header exactly as the server sends it.
- Read each missing flag with what it exposes, rather than as a checklist item.
- Set HttpOnly on anything a script never needs to read.
- Check scope and lifetime as well as the three main flags.
MDN’s Set-Cookie reference documents every attribute. Other security tools are in the tools directory.
Frequently asked questions
What does HttpOnly actually prevent?
It stops JavaScript reading the cookie, so a cross-site scripting flaw can’t simply steal the session token. It doesn’t prevent XSS — it limits what one successful XSS can take.
What should SameSite be set to?
Lax is a sensible default and what browsers now apply when the attribute is absent. Strict is stronger and breaks links arriving from other sites. None requires Secure and should be deliberate.
Does Secure matter on an HTTPS-only site?
Yes. Without it, a single accidental plain-HTTP request sends the cookie in clear text before any redirect happens.
Final thought
Set all three on every session cookie and narrow the scope. They defend against different attacks, and having two of three is having a gap you can name.