The hook
Three flags on a Set-Cookie line decide whether an XSS in your app becomes an inconvenience or a session hijack. They cost nothing to set, every modern framework supports them, and yet auth cookies routinely ship to production missing one or more. The bug is operational, not technical: someone wrote the cookie-issuing code in 2019 before SameSite became the browser default, nobody updated it when defaults changed, and the cookie has been quietly missing protections for years. The good news is that fixing this is one config change. The bad news is that until you fix it, any XSS or CSRF in your app skips the entire 'session cookie defense' layer.
Kako deluje
HttpOnly tells the browser to hide the cookie from JavaScript — `document.cookie` simply won't return it. This is the single biggest XSS-blast-radius reducer: an attacker with script execution in your origin can do many things, but stealing a HttpOnly cookie isn't one of them. Secure tells the browser to send the cookie only over HTTPS, so an attacker on hostile WiFi can't sniff it from a downgraded connection. SameSite=Lax (the modern browser default) blocks the cookie on cross-site form POSTs and most cross-site fetches, eliminating classic CSRF without requiring CSRF tokens. SameSite=Strict goes further (no cookie on any cross-site request, including top-level navigations) at the cost of breaking some legit cross-site auth flows. The `__Host-` cookie name prefix is the strongest possible binding — it requires Secure, no Domain attribute, and Path=/ — making the cookie inseparable from your origin.
The variants
Missing HttpOnly
JavaScript-readable session cookie. Any XSS exfiltrates it in one fetch. Most consequential single missing flag.
Missing Secure
Cookie sent over plain HTTP if any link to http:// gets clicked. Hostile-WiFi sniff vector. Combined with no HSTS, trivially exploitable.
Missing or None SameSite
Modern browsers default to Lax for cookies without an explicit SameSite attribute, but explicit `SameSite=None` (sometimes used for cross-domain SSO) re-enables CSRF if you don't have token-based defenses.
Auth state in localStorage
Some apps skip cookies entirely and store JWTs in localStorage. localStorage is JS-readable by definition; HttpOnly doesn't apply. Architecturally regressive.
The blast radius
Without HttpOnly, every XSS — DOM-based or reflected — escalates to full account takeover via cookie exfiltration. Without Secure, a hostile network connection (coffee shop WiFi, captive portal, conference WiFi) can sniff sessions whenever the user clicks any plain-http link to your domain. Without SameSite, classic CSRF returns: any other site the user visits can submit forged forms to your endpoints carrying their session.
// what fixvibe checks
What FixVibe checks
FixVibe checks this class with high-confidence, non-destructive signals and only reports actionable evidence. For check-specific questions about exact detection heuristics, active payload details, or source-code rule patterns, contact support@fixvibe.app.
Ironclad defenses
Set HttpOnly + Secure + SameSite=Lax on every session and auth cookie. Modern frameworks make this the default — Express's `cookie` package, Next.js's `cookies()` API, Django's `SESSION_COOKIE_SECURE`/`SESSION_COOKIE_HTTPONLY`/`SESSION_COOKIE_SAMESITE`, Laravel's `config/session.php` — but verify in production. Use `__Host-` cookie name prefix (`__Host-session`) for the strongest possible binding to your origin. Don't store auth state in localStorage; it's JavaScript-readable and the entire point of HttpOnly is to defeat that. For cross-domain SSO scenarios that require SameSite=None, pair it with strong CSRF defenses (custom headers, tokens) so you're not relying on browser-level cookie isolation alone. Audit any cookie set without explicit attribute config — defaults change, and silent regressions happen.
