Support Library
Secure, HttpOnly and SameSite Cookie Flags
A session cookie is the key to a signed-in account: whoever has it is logged in. Three attributes on the Set-Cookie header decide where that key can travel. Secure keeps it off plain HTTP, HttpOnly hides it from page scripts, and SameSite limits when other sites can make the browser send it.
The short answer
Set session and authentication cookies like this:
Set-Cookie: session=abc123; Path=/; Secure; HttpOnly; SameSite=LaxUse Secure on every cookie of an HTTPS site, HttpOnly on every cookie that page scripts do not need to read, and SameSite=Lax or Strict unless the cookie must work inside other sites.
How cookies leak
How DNS Panopticon detects it
Security Posture reads the Set-Cookie headers your homepage sends and checks each cookie’s flags. Cookies whose names look like sessions or sign-ins (containing sess, sid, auth, token, login, jwt or remember) are held to the HttpOnly rule. The result appears on the Website Application Security card.
| Finding | Severity | When it appears |
|---|---|---|
| Cookies without the Secure flag | Medium | The site uses HTTPS but sets cookies without Secure, so the browser would also send them over plain http. Up to four names are listed. |
| Session cookies readable by scripts | Low | A cookie with a session-like name has no HttpOnly flag. |
| Cookies are flagged safely | Pass | Every cookie on the homepage has the expected flags. |
Only cookies set by the homepage response are seen. Cookies set after sign-in, by JavaScript, or on other pages are not, so check them in the browser too. SameSite is explained here but not graded.
How to check it yourself
| Command or tool | What to look for |
|---|---|
| curl -sI https://example.com | Each set-cookie line and whether it ends with Secure, HttpOnly and a SameSite value. |
| curl -s -o /dev/null -D - https://example.com/login | The same for a sign-in page (on Windows, use -o NUL). |
In Chrome or Edge, open developer tools, then Application → Cookies; in Firefox, Storage → Cookies. The table has columns for Secure, HttpOnly and SameSite for every cookie the site has set, including ones set after you sign in.
What each flag does
| Attribute | What it does | What goes wrong without it |
|---|---|---|
| Secure | The browser only sends the cookie over HTTPS. | One http:// request, such as an old link or an image, sends the cookie in the clear. |
| HttpOnly | Page scripts cannot read the cookie through document.cookie. | Any cross-site scripting bug lets an attacker copy the session. |
| SameSite=Lax | Sent on top-level navigation from other sites, not on their embedded requests or form posts. | Other sites can make the browser send it with forged requests (CSRF). |
| SameSite=Strict | Never sent on requests started by another site. | As above; Strict also means users arriving from a link are not signed in on that first page. |
| SameSite=None | Sent everywhere; must be combined with Secure. | Needed only for cookies used inside other sites, such as embedded widgets. |
| __Host- prefix | A name starting with __Host- requires Secure, Path=/ and no Domain. | Without it, a subdomain could set a cookie that overrides yours. |
Current browsers treat a cookie with no SameSite attribute as Lax, but setting it explicitly keeps behaviour the same in every browser.
Why it matters
- Session hijacking. A stolen session cookie lets an attacker use the account without a password or MFA, until the session expires.
- Cross-site scripting. Most XSS attacks aim for the session cookie first. HttpOnly takes that prize away, even though the script can still act inside the page.
- Insecure links. Even an HTTPS-only site can be reached over http:// by a typed address or an old link. Without Secure, the cookie goes along. HSTS helps, but Secure is the direct fix.
How to fix it
Cookies are set by your application or platform, so the fix is usually a configuration setting rather than web server code:
| Platform | Setting |
|---|---|
| PHP | In php.ini: session.cookie_secure = 1, session.cookie_httponly = 1, session.cookie_samesite = "Lax" |
| ASP.NET Core | CookieSecurePolicy.Always, HttpOnly = true and SameSite = SameSiteMode.Lax in the cookie or session options |
| ASP.NET (web.config) | <httpCookies requireSSL="true" httpOnlyCookies="true" sameSite="Lax" /> under system.web |
| Express | cookie: { secure: true, httpOnly: true, sameSite: 'lax' } in express-session |
| Django | SESSION_COOKIE_SECURE = True, CSRF_COOKIE_SECURE = True; HttpOnly and Lax are the defaults |
| nginx (proxy) | proxy_cookie_flags ~ secure httponly samesite=lax; (nginx 1.19.3 and later) to add flags to an upstream app’s cookies |
- Start with session and sign-in cookies, then the rest.
- Leave HttpOnly off only for cookies your own JavaScript must read, such as a UI preference or a CSRF token read by a script. Never for the session.
- Third-party cookies from analytics or chat tools are set by those vendors’ scripts; check their settings, or consider whether you need them.
- Sign everyone out after changing session cookie settings if you suspect cookies were exposed, so old sessions stop working.
FAQ
Does HttpOnly stop cross-site scripting?
No. An injected script can still act inside the page as the user. HttpOnly only stops it from copying the session cookie to use elsewhere. A Content-Security-Policy is what limits injected scripts.
Our analytics cookie (_ga) is flagged. Should it be HttpOnly?
No: the analytics script needs to read it. DNS Panopticon only applies the HttpOnly rule to cookies whose names look like sessions or sign-ins. All cookies on an HTTPS site should still have Secure.
Should I use SameSite=Strict?
For highly sensitive apps, such as banking or admin consoles, Strict is a good choice. For most sites, Lax balances protection with keeping users signed in when they follow a link to you.
Can I set these flags in a CDN instead of the app?
Sometimes. Some CDNs and reverse proxies can rewrite Set-Cookie headers, as nginx’s proxy_cookie_flags does. Fixing it in the application is more reliable because it covers every response.
Sources and further reading
- RFC 6265: HTTP State Management Mechanism: the cookie standard, including Secure and HttpOnly
- IETF draft: Cookies (RFC 6265bis): SameSite and cookie prefixes
- MDN: Using HTTP cookies
- MDN: Set-Cookie
- OWASP Session Management Cheat Sheet
- web.dev: SameSite cookies explained
- nginx: proxy_cookie_flags