Secure cookies: never let your session cookie travel in cleartext
The Secure attribute tells browsers to send your session cookie only over https, so it can never be read off an unencrypted request
The threat
Your session cookie is what keeps a visitor logged in. Without the Secure attribute, the browser will attach that cookie to any request to your domain, including one that goes out over plain http://. That can happen more easily than you think: someone types your bare domain, clicks an old http:// link, or a stray http:// subresource fires before your redirect runs. In every one of those cases the cookie rides along unencrypted.
On shared or public wifi, an unencrypted cookie is a session waiting to be copied. Someone on the same network reads it off the wire and replays it, and now they are the visitor: logged in, no password needed. The Secure attribute closes that door by telling the browser to send the cookie only over https, so it never appears on a cleartext request in the first place.
The exact fix
Add Secure to the Set-Cookie header. A hardened session cookie looks like this:
Set-Cookie: sid=abc123; Path=/; Secure; HttpOnly; SameSite=Lax
The Secure token is the whole fix. Most frameworks set it for you with one flag.
Express (express-session or res.cookie).
app.use(session({
secret: process.env.SESSION_SECRET,
cookie: {
secure: true, // only sent over https
httpOnly: true,
sameSite: 'lax',
maxAge: 1000 * 60 * 60 * 8,
},
}))
PHP (set params before session_start()).
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => true, // https only
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();
Or set it globally in php.ini: session.cookie_secure = 1.
- Any other stack: the goal is identical, get the literal
Secureattribute onto theSet-Cookieresponse header for the session cookie. - Go one better with
__Host-. Naming the cookie__Host-sidmakes the browser reject it unless it isSecure, hasPath=/, and carries noDomain. It is the strongest binding available, and it forcesSecureon by definition.
Behind a proxy or CDN (Netlify, Heroku, nginx)? Express only sets a
Securecookie when it believes the request was https. Terminated TLS at the edge can hide that, so addapp.set('trust proxy', 1), otherwisesecure: truecan silently drop the cookie and log everyone out.
Verify it
curl -sI https://yourdomain.com/login | grep -i set-cookie
You want the Secure token present in the attributes, for example Set-Cookie: sid=...; Secure; HttpOnly; SameSite=Lax. The other half of the proof: request the same cookie-setting page over http:// and confirm the browser does not store or resend it.
Proof
The ApeCyber scanner reads the Set-Cookie header on a normal request, from the outside, touching nothing, so a session cookie missing Secure is visible exactly the way any network observer would see it. The same header discipline is what carried apecyber.com and dev3lop.com to A / 100. One attribute, five minutes, a clean โ10 off the posture score.