Cookie Security: The Complete Guide for Web Developers
Cookies are the backbone of web authentication. Session tokens, JWTs, preference data — all stored in cookies. If your cookies aren't properly secured, your authentication is compromised.
The Three Essential Cookie Flags
1. Secure Flag
Set-Cookie: session=abc123; Secure
What it does: Cookie is only sent over HTTPS connections. Never transmitted over plain HTTP.
Why it matters: Without the Secure flag, an attacker on the same network (coffee shop WiFi) can intercept your session cookie via a man-in-the-middle attack.
Set it: Always. There is no valid reason to omit the Secure flag on authentication cookies in production.
2. HttpOnly Flag
Set-Cookie: session=abc123; HttpOnly
What it does: Cookie is inaccessible to JavaScript's document.cookie API.
Why it matters: If an attacker finds an XSS vulnerability in your app, they can't steal the session cookie via JavaScript. The cookie is only sent automatically with HTTP requests.
Set it: Always for session and authentication cookies. Only omit for cookies that JavaScript genuinely needs to read (rare).
3. SameSite Attribute
Set-Cookie: session=abc123; SameSite=Lax
What it does: Controls when cookies are sent in cross-site requests.
| Value | Behavior |
|---|---|
Strict | Cookie only sent on same-site requests. Most secure, but breaks some UX (e.g., clicking a link from email won't be logged in) |
Lax | Cookie sent on same-site requests + top-level navigations (GET). Best balance of security and usability |
None | Cookie sent on all cross-site requests. Requires Secure flag. Only use if your app needs cross-site cookie access (embedded iframes, third-party integrations) |
Lax for most applications. Strict for high-security apps. Never None unless you explicitly need cross-site cookies.
Common Mistakes We See
1. Session Cookie Without Any Flags
Set-Cookie: session=abc123
No Secure, no HttpOnly, no SameSite. This is the worst case — the cookie is vulnerable to interception, XSS theft, and CSRF attacks simultaneously.
2. SameSite=None Without Secure
Set-Cookie: session=abc123; SameSite=None
Browsers will reject this. If you set SameSite=None, you must also set Secure. This is a spec requirement.
3. Short or Missing Expiry
Set-Cookie: session=abc123; HttpOnly; Secure; Max-Age=31536000
A session cookie that lasts a year? That's too long. If a cookie is compromised, the attacker has a year-long window.
Best practice: Authentication cookies should expire in hours or days, not months or years. Use sliding expiration for active sessions.The Correct Setup
Here's the gold standard for a session cookie:
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/; Max-Age=86400
In Express.js:
res.cookie('session', token, {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 86400000, // 24 hours
path: '/'
});
What TrustGate Checks
When you scan your application with TrustGate, we check:
- ✅ Secure flag on all cookies
- ✅ HttpOnly flag on session cookies
- ✅ SameSite attribute set
- ✅ Reasonable expiration times
- ✅ No sensitive data in cookie values
Fix your cookies. Protect your sessions. Scan now.