HttpOnly cookies: put your session cookie out of JavaScript's reach
The HttpOnly attribute hides your session cookie from all page JavaScript, so an injected script cannot read it and steal the session
The threat
By default, any JavaScript running on your page can read your cookies through document.cookie. That is fine until the day a script you did not intend runs on your page: a cross-site scripting (XSSXSSAttackCross-Site Scripting: an attack that injects attacker-controlled JavaScript into your page to steal sessions, keylog, or act as the user. A strong CSP is the primary defense.) bug, a compromised third-party widget, a bad ad. The moment that happens, the attackerβs script reads the session cookie and sends it off to their server. No password prompt, no second exploit needed, they simply become the logged-in visitor.
The HttpOnly attribute cuts that chain. It tells the browser to keep the cookie completely invisible to JavaScript: document.cookie returns nothing for it, and no script can touch its value. The cookie still travels on normal requests and keeps the session working, it just stops being readable by code. So even if an injection lands on your page, the session cookie is not the prize it walks away with.
The exact fix
Add HttpOnly to the Set-Cookie header. A hardened session cookie looks like this:
Set-Cookie: sid=abc123; Path=/; Secure; HttpOnly; SameSite=Lax
Express. Note that express-session sets httpOnly: true by default, but a manual res.cookie(...) call does not, so set it explicitly:
res.cookie('sid', token, {
httpOnly: true, // hidden from document.cookie
secure: true,
sameSite: 'lax',
})
PHP (set params before session_start()).
session_set_cookie_params([
'path' => '/',
'secure' => true,
'httponly' => true, // no JavaScript access
'samesite' => 'Lax',
]);
session_start();
Or globally in php.ini: session.cookie_httponly = 1.
- Any other stack: the aim is the same, get the literal
HttpOnlyattribute onto the session cookieβsSet-Cookieheader. - A cookie your front-end genuinely must read (a CSRF token, a UI preference) is a separate, non-sensitive cookie. Keep
HttpOnlyon the session cookie regardless.
HttpOnlylimits the damage from XSS, it does not prevent XSS. It removes the easiest payoff (cookie theft), but an injected script can still act inside the page. Pair it with a strong Content-Security-Policy so the injection never runs in the first place.
Verify it
curl -sI https://yourdomain.com/login | grep -i set-cookie
The Set-Cookie line should include HttpOnly. For a hands-on confirmation, open your logged-in site with DevTools and type document.cookie in the Console: the session cookie must not appear in the output. In the Application panel, under Cookies, its HttpOnly column should show a check.
Proof
The ApeCyber scanner sees the missing HttpOnly attribute on a normal page response, from the outside, touching nothing, the same view any script on the page would have. The header discipline behind it is what took dev3lop.com from a failing grade to A / 100. It is a one-word change: a clean β10 off the posture score, in about five minutes.