What Each Flag Actually Stops
- Secure - the browser will never send this cookie over plain HTTP, only HTTPS. Without it, a session cookie can be sniffed by anyone on the same network as an active man-in-the-middle, or leaked the moment a user follows an old
http://link. - HttpOnly - JavaScript (
document.cookie) can't read this cookie at all. Without it, a single successful XSS injection anywhere on your site can exfiltrate the session cookie directly, turning a script-injection bug into full account takeover. - SameSite - controls whether the cookie is sent on cross-site requests. Without it (or set to
NonewithoutSecure), the cookie rides along on requests initiated from other sites, which is the mechanism CSRF attacks depend on.
How to Fix It
Set all three explicitly on session/auth cookies
1Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/Node/Express example
1app.use(session({
2 secret: process.env.SESSION_SECRET,
3 cookie: {
4 secure: true, // HTTPS only
5 httpOnly: true, // no JS access
6 sameSite: "lax", // blocks most cross-site CSRF vectors
7 },
8}));Pick SameSite based on what the cookie actually needs to survive
Strict- the tightest option; the cookie is never sent on any cross-site request, including a user clicking a link into your site from elsewhere.Lax- the sane default for most session cookies; blocks cross-site POSTs (the main CSRF vector) while still allowing the cookie on top-level navigation.None- required for cookies that genuinely need to work across sites (an embedded widget, for example) - butNonewithoutSecureis rejected by modern browsers outright.
How Scanverra Detects This
Scanverra's security scan inspects every Set-Cookie header your site sends and flags each cookie missing Secure, HttpOnly, or SameSiteindividually, so you get a specific list of which cookies need which flag rather than a single generic warning.