UnveilTech

UnveilScan Blog

← All articles

Try UnveilScan free

Cookie flags audit: Secure / HttpOnly / SameSite in 2 lines

Posted 2026-04-29 · 5 min read · WEBcookies

Three cookie attributes mitigate three different attack classes. Setting all three on every authentication cookie is the lowest-effort, highest-value security improvement most apps could make. We see them missing on ~30% of the domains we scan.

The three flags

FlagWhat it stops
SecureCookie sent only over HTTPS. Defends against MITM on the network path.
HttpOnlyCookie not exposed to JavaScript. Defends against XSS-based theft.
SameSite=Lax / StrictCookie not sent on cross-site requests. Defends against CSRF.

SameSite values

The __Host- prefix (the bonus)

A cookie named __Host-Session=... has automatic guarantees enforced by the browser:

This is the cleanest defence against subdomain-takeover-based session theft (cf. our subdomain takeover article). If a subdomain is compromised, it can't read or write your __Host- cookie because the browser refuses to bind it to anything but the exact host.

UnveilScan uses __Host-unveilscan_session and __Host-unveilscan_csrf for this reason. Cost: zero. Benefit: real.

How to set the flags

nginx

# Doesn't set cookies itself; rewrites the Set-Cookie header from upstream.
# Add flags to every upstream-set cookie:
proxy_cookie_path / "/; Secure; HttpOnly; SameSite=Lax";

Apache (httpd)

Header always edit Set-Cookie ^(.*)$ "$1; Secure; HttpOnly; SameSite=Lax"

Express (Node.js)

// Using cookie-session or express-session
app.use(session({
  secret: process.env.SESSION_SECRET,
  cookie: {
    secure: true,         // HTTPS only
    httpOnly: true,
    sameSite: 'lax',
    maxAge: 86400000,
  },
  name: '__Host-app_session',  // bonus: __Host- prefix
}));

Django

# settings.py
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True   # default since Django 1.7
SESSION_COOKIE_SAMESITE = 'Lax'  # default since Django 2.1
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Lax'

Spring Boot

# application.properties
server.servlet.session.cookie.secure=true
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.same-site=lax

PHP

// php.ini
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = "Lax"

// Or per-script
session_set_cookie_params([
  'secure' => true, 'httponly' => true, 'samesite' => 'Lax',
]);

Verifying

$ curl -sI https://example.com/login -X POST -d 'user=foo&pass=bar' \
  | grep -i set-cookie
Set-Cookie: __Host-app_session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax

All three flags + __Host- prefix + Path=/ = clean.

Common mistakes

  1. Forgetting Secure on auth cookies when running behind a TLS-terminating reverse proxy. The cookie sees plain HTTP at the upstream server level — frameworks default to no Secure flag. Override explicitly.
  2. SameSite=None without Secure — modern browsers reject this. Always pair the two.
  3. SameSite=Strict on session cookies — breaks "click email link → land logged in". Use Lax instead unless you have a hard reason.
  4. Sending JWT in cookies without HttpOnly — exposes the token to any XSS. Either store JWTs in HttpOnly cookies or accept they live in localStorage with the security trade-off.

How UnveilScan checks

Our headers checker parses every Set-Cookie header in the apex response:

Audit your cookies

Free Basic scan parses Set-Cookie headers and reports missing flags by cookie name.

Run a scan