Security guide
A session cookie is the key to an account, and the attributes it is set with decide who can pick that key up. This guide covers the flags that matter, the settings for a typical stack, and where cookie security ends and consent begins.
01 Why it matters
Whoever holds a valid session cookie is, as far as the server is concerned, the logged-in user. No password is needed and no second factor is asked for. That makes the way a cookie is set at least as important as the way the session itself is generated: the attributes on the Set-Cookie header decide whether scripts can read it, whether it travels over an unencrypted connection and whether another site can make the browser send it.
This is a different question from cookie consent. Consent is about whether a cookie may be set at all and what it is used for. Cookie security is about whether the cookies you legitimately set can be stolen or misused. A strictly necessary session cookie needs no banner and still needs every flag on this page.
02 The attributes
Secure What it does. Tells the browser to send this cookie only over HTTPS connections, never over plain HTTP.
Why it matters. Without it, a single request that slips onto HTTP puts the cookie on the wire in clear text. That is enough to take over the session, and the request does not have to be one the user made deliberately.
Set-Cookie: session=abc123; Secure HttpOnly What it does. Hides the cookie from JavaScript: it is sent with requests, but document.cookie cannot read it.
Why it matters. It is what keeps a cross-site scripting bug from turning into an account takeover. Without HttpOnly, any script that reaches the page, including one from a compromised third-party dependency, can read the session and send it elsewhere.
Set-Cookie: session=abc123; Secure; HttpOnly SameSite What it does. Controls whether the cookie travels with requests that come from another site. Lax sends it on top-level navigation only, Strict never sends it cross-site, None sends it always and then requires Secure.
Why it matters. It is the built-in defence against cross-site request forgery. With Lax, a form on an attacker page can no longer make the browser perform a state-changing request as the logged-in user.
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax Domain / Path What it does. Domain and Path decide which hosts and which URLs the cookie is sent to. Leaving Domain out keeps the cookie on the exact host that set it.
Why it matters. A Domain set to the parent domain hands the cookie to every subdomain, including ones run by other teams or by a hosting product you do not control. Narrow scope is free protection.
Set-Cookie: session=abc123; Path=/; Secure; HttpOnly Max-Age What it does. Max-Age and Expires decide how long the cookie survives. Without either, it is a session cookie and disappears when the browser closes.
Why it matters. A stolen cookie is useful for exactly as long as it stays valid. Short lifetimes plus server-side invalidation on logout limit the damage; a remember-me cookie that lives for a year does the opposite.
Set-Cookie: session=abc123; Max-Age=3600; Secure; HttpOnly __Host- Prefix What it does. A cookie whose name starts with __Host- is only accepted when it is Secure, has no Domain attribute and uses Path=/.
Why it matters. It makes the rules enforceable by the browser instead of by convention: a subdomain cannot overwrite the cookie with a weaker version, because the browser rejects anything that does not meet the conditions.
Set-Cookie: __Host-session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax 03 Setting it up
Session cookies are set by your application, not by your web server, so this is a change in your runtime configuration rather than in nginx. In PHP you set the session flags with ini_set before the session starts, or equivalently in php.ini; other stacks have an equivalent block. Set them once, then check the live response rather than the configuration file.
ini_set( 'session.cookie_secure', '1' );
ini_set( 'session.cookie_httponly', '1' );
ini_set( 'session.cookie_samesite', 'Lax' );
ini_set( 'session.use_strict_mode', '1' ); Cookies set by JavaScript, by a consent tool or by an embedded third party do not go through that configuration. They need the same flags where they are created, and they are the ones a scan most often finds.
04 Questions
Lax is the usual answer, because Strict also drops the cookie when a visitor arrives from an external link, which logs them out on the way in. Strict is worth it for cookies that only guard state-changing actions.
Yes. Secure is what makes the rule enforceable in the browser rather than dependent on your redirects, and it is required for SameSite=None. It costs nothing to set.
Not always. Some cookies exist precisely so that scripts can read them, such as a CSRF token or a stored theme choice. The flag matters for anything that authenticates a user, and that is what a finding points at.
It does not overlap. A banner is about permission to set a cookie at all, these attributes are about how safely a cookie you are allowed to set behaves. Our privacy guide covers the consent side.
05 In depth
Cookies sit between transport and page. These guides cover both sides.
What each response header does, which ones your site should send and how to configure them correctly.
The strongest defence against cross-site scripting: which directives to set, how to roll a policy out in report-only mode and how to reach an enforcing policy without breaking your site.
Strict-Transport-Security explained: what max-age, includeSubDomains and preload actually do, and why the preload list is a decision you cannot quickly undo.
How an invisible overlay turns a visitor click into an action on your site, and the two headers that stop it: X-Frame-Options for older clients, frame-ancestors for everything else.
Which part of your URLs travels to other sites when a visitor clicks away: the five policy values that matter, what each one gives up and the one to set by default.
Switch off camera, microphone, geolocation and payment for your site and everything it embeds: the allow-list syntax, and why a feature you did not name is not a feature you turned off.
The records that stop someone sending mail in your name, and the one that keeps your DNS answers honest: what each does and the order to introduce them in.
The file that tells a researcher where to report a vulnerability. Two mandatory fields, ten minutes of work, and the difference between a private report and a public one.
A header that is right today can be gone after the next deploy. Three ways to notice: a cron job with curl, a check in your CI pipeline and a scheduled scan, with what each of them catches and misses.
How a policy changes quietly through deploys, plugins and CDN rules, and how to catch it: a header diff, violation reports through report-to, and what a scan comparison can and cannot show.
Keep reading
Every guide stands on its own, and together they cover what our scanner looks at. Pick the one closest to your next question.
Our free Quickscan reads the Secure, HttpOnly and SameSite attributes of every cookie your site sets, alongside your security headers and privacy signals.