mediumSeverity: mediumRisk ratingHow usable this gap is to an attacker. Severity sets the posture penalty: critical โˆ’40, high โˆ’20, medium โˆ’10, low โˆ’4, info โˆ’1. Higher severity means fix it sooner.App server (Set-Cookie)Where it livesImplementationThis fix is applied in: App server (Set-Cookie). That's the surface you'll edit, DNS, response headers, or a static file.~5 minTime to fixEffortRoughly 5 minutes of hands-on work, propagation aside. Most of these are copy-paste.+10 posture+10 postureScore impactPoints this fix recovers in the ApeCyber posture score (0โ€“100). Posture = 100 minus the severity penalty of every open finding; clearing this finding adds these points back.

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 Secure attribute onto the Set-Cookie response header for the session cookie.
  • Go one better with __Host-. Naming the cookie __Host-sid makes the browser reject it unless it is Secure, has Path=/, and carries no Domain. It is the strongest binding available, and it forces Secure on by definition.

Behind a proxy or CDN (Netlify, Heroku, nginx)? Express only sets a Secure cookie when it believes the request was https. Terminated TLS at the edge can hide that, so add app.set('trust proxy', 1), otherwise secure: true can 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.