Skip to main content
Back to blog
February 21, 2026|8 min read|Tutorials

Cookie Security: Every Flag Developers Must Set in 2025

Insecure cookies are one of the top causes of session hijacking. Learn what Secure, HttpOnly, SameSite, and other cookie attributes do — with real examples for Express, Django, Laravel, and Next.js.

ZeriFlow Team

987 words

Cookies are the backbone of web authentication. Every time a user logs in, their session token is stored in a cookie. If that cookie is not properly secured, an attacker can steal it and impersonate the user. This is not a theoretical risk — session hijacking through insecure cookies remains one of the most common web attacks.

The good news is that securing cookies is straightforward. A handful of flags and attributes, properly configured, can eliminate entire categories of attacks. This guide covers every flag you need to know, explains what each one prevents, and shows you how to set them in the most popular web frameworks.

The Cost of Insecure Cookies

Before diving into the technical details, consider what an insecure session cookie enables:

  • Session hijacking — An attacker steals the cookie and takes over the user account
  • Cross-site request forgery (CSRF) — An attacker tricks the user's browser into making authenticated requests
  • Cross-site scripting (XSS) data theft — Malicious JavaScript reads cookie values and sends them to the attacker
  • Man-in-the-middle interception — Cookie transmitted over HTTP can be read by anyone on the network

Each of these attacks is preventable with the right cookie configuration.

Secure

The Secure flag ensures the cookie is only sent over HTTPS connections. Without it, the cookie will be transmitted in plain text over HTTP, where anyone on the same network can intercept it.

Set-Cookie: session=abc123; Secure

When to use it: Always. Every cookie that contains sensitive data (especially session tokens) must have the Secure flag. There is no valid reason to send session cookies over HTTP in 2025.

Common mistake: Setting the Secure flag in production but not in local development, then forgetting to re-enable it. Use environment-based configuration to handle this automatically.

HttpOnly

The HttpOnly flag prevents JavaScript from accessing the cookie via document.cookie. This is your primary defense against XSS-based session theft.

Set-Cookie: session=abc123; HttpOnly

Why it matters: Even if an attacker finds an XSS vulnerability in your application, they cannot steal HttpOnly cookies. The cookie is still sent with requests, but it is invisible to client-side scripts.

When to skip it: Only for cookies that JavaScript legitimately needs to read, like theme preferences or UI state. Never skip HttpOnly for session tokens or authentication cookies.

SameSite

The SameSite attribute controls whether the cookie is sent with cross-site requests. It is your primary defense against CSRF attacks.

Three values:

  • Strict — Cookie is never sent with cross-site requests. Most secure, but can break legitimate flows (e.g., clicking a link from an email to your site will not include the cookie).
  • Lax — Cookie is sent with top-level navigation (clicking links) but not with embedded requests (forms, images, iframes). This is the recommended default.
  • None — Cookie is sent with all cross-site requests. Requires the Secure flag. Only use this for legitimate cross-site scenarios like embedded widgets or OAuth flows.
Set-Cookie: session=abc123; SameSite=Lax

Default behavior: Modern browsers default to SameSite=Lax if no attribute is set. However, explicitly setting it is best practice for clarity and compatibility.

Domain and Path

The Domain attribute controls which domains receive the cookie. The Path attribute restricts the cookie to specific URL paths.

Set-Cookie: session=abc123; Domain=example.com; Path=/app

Best practice: Set the Domain to your exact domain (not a wildcard that includes all subdomains) and the Path to the most specific path possible. This limits cookie exposure.

Max-Age and Expires

These attributes control how long the cookie persists. A session cookie (no Max-Age or Expires) is deleted when the browser closes. A persistent cookie lives for the specified duration.

Set-Cookie: session=abc123; Max-Age=3600

Security guideline: Session tokens should have a short lifetime (1-4 hours for active sessions, 30 minutes for sensitive operations). Long-lived cookies increase the window for session hijacking.

Framework Examples

Express.js (Node.js)

javascript
app.use(session({
  cookie: {
    secure: true,
    httpOnly: true,
    sameSite: 'lax',
    maxAge: 3600000,
    domain: 'example.com',
    path: '/'
  }
}));

Django (Python)

python
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_AGE = 3600
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True

Laravel (PHP)

php
// config/session.php
'secure' => true,
'http_only' => true,
'same_site' => 'lax',
'lifetime' => 60, // minutes

Next.js API Routes

javascript
res.setHeader('Set-Cookie', [
  `session=${token}; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600`
]);

Use this checklist for every cookie your application sets:

  1. 1Session cookies have the Secure flag
  2. 2Session cookies have the HttpOnly flag
  3. 3SameSite is set to Lax or Strict
  4. 4Cookie domain is as specific as possible
  5. 5Session lifetime is reasonable (not months)
  6. 6No sensitive data stored directly in cookie values
  7. 7Cookie names do not reveal technology stack (avoid PHPSESSID, JSESSIONID)
  8. 8Third-party cookies are audited and minimized
  9. 9Cookie consent is implemented for tracking cookies
  10. 10Cookies are tested with and without HTTPS

You can check your cookie configuration in several ways:

  • Browser DevTools: Open Application > Cookies to see all flags for each cookie
  • ZeriFlow scan: Automatically checks all cookies for missing security flags and reports specific recommendations
  • curl command: Use curl -I https://yoursite.com and inspect the Set-Cookie headers

Proper cookie flags are necessary but not sufficient. A complete cookie security strategy also includes:

  • Token rotation — Issue a new session token after login and privilege escalation
  • Token binding — Tie the session to the user's IP or user-agent to detect theft
  • Logout invalidation — Server-side session destruction, not just cookie deletion
  • Cookie prefixes — Use __Secure- and __Host- prefixes for additional browser-enforced security

Getting cookie security right is one of the highest-impact, lowest-effort improvements you can make. Set the flags, test them, and automate the verification with regular ZeriFlow scans.

Ready to check your site?

Run a free security scan in 30 seconds.

Related articles

Keep reading