Insecure Cookies Explained

TL;DR

Three missing flags, three ways to lose a session cookie: no HttpOnly and XSS can read it straight out of the browser, no Secure and it crosses the network in plain text, no SameSite and CSRF rides along for free. Set all three on every auth cookie: HttpOnly, Secure, and SameSite=Lax or Strict. Skip one and you've left a door open.

FlagWhat It DoesPrevents
HttpOnlyCookie not accessible via JavaScriptXSS cookie theft
SecureCookie only sent over HTTPSNetwork interception
SameSite=StrictCookie only sent on same-site requestsCSRF attacks
SameSite=LaxSent on same-site + top-level navigationMost CSRF attacks

The Problem

Insecure cookie setting
// Missing all security flags!
res.cookie('session', token);

// What this actually means:
// - JavaScript can read it (XSS can steal it)
// - Sent over HTTP (can be intercepted)
// - Sent on cross-site requests (CSRF possible)

The Fix

Secure cookie settings
// Express example
res.cookie('session', token, {
  httpOnly: true,   // Can't be accessed by JavaScript
  secure: true,     // Only sent over HTTPS
  sameSite: 'lax',  // Not sent on cross-site requests
  maxAge: 7 * 24 * 60 * 60 * 1000,  // 7 days
  path: '/'
});

// Next.js API route
import { cookies } from 'next/headers';

cookies().set('session', token, {
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production',
  sameSite: 'lax',
  maxAge: 60 * 60 * 24 * 7
});

Should I use SameSite Strict or Lax?

Lax, for most cases. Strict is stricter than most apps can afford: it breaks the flow where a user clicks a link from an email and lands logged out. Lax still blocks cross-site POST requests; it just lets the cookie through on top-level navigation.

What about cookie prefixes like __Host-?

They add a second layer. __Host- requires Secure, no Domain, and Path=/. __Secure- just requires the Secure flag. Either one stops a subdomain from setting a cookie your main domain will trust.

Do I need Secure in development?

Not usually. Localhost is exempted by most browsers. secure: process.env.NODE_ENV === 'production' applies the flag only where it matters.

Our scanner verifies your cookies have proper security flags.

Vulnerability Guides

Insecure Cookies Explained