Cookie Attributes: HttpOnly, Secure, SameSite and More

Cookie attributes control how cookies are stored, sent, and accessed to ensure security.

Cookie Attributes

Cookies are small but powerful. The attributes you set on a cookie control who can read it, when it expires, and whether it travels with cross-site requests. Getting these wrong can expose your users to serious security risks including session hijacking, cross-site scripting attacks, and cross-site request forgery.

What Are Cookie Attributes

When a server sets a cookie via the Set-Cookie HTTP response header, it can include attributes that control how the browser handles that cookie. These attributes are instructions for the browser only. They are never sent back to the server as part of subsequent requests, and the server cannot read them once the cookie is set.

A cookie without any attributes is accessible to JavaScript, sent over both HTTP and HTTPS, sent with cross-site requests, and valid only for the current browser session. That default behaviour is insecure for anything sensitive. Attributes exist to tighten these defaults and reduce the attack surface of your cookies.

Cookie Attributes Reference

AttributeWhat It DoesSecurity Impact
HttpOnlyPrevents JavaScript from reading the cookie via document.cookieProtects session cookies from being stolen by XSS attacks
SecureCookie is only sent over HTTPS connections, never over plain HTTPPrevents interception on unencrypted connections
SameSite=StrictCookie is never sent with any cross-site request, including top-level navigationStrongest CSRF protection, but may break OAuth flows and external links
SameSite=LaxCookie is sent on top-level navigation but not on cross-site subresource requestsBalanced CSRF protection, the recommended default for most applications
SameSite=NoneCookie is sent with all requests including cross-site requestsRequires the Secure attribute. Used for embedded content, iframes, and SSO flows.
ExpiresSets a specific date and time at which the cookie expires (persistent cookie)If not set, the cookie is deleted when the browser session ends
Max-AgeSets the cookie's lifetime in seconds from the moment it is createdPreferred over Expires because it avoids clock skew issues between client and server
DomainSpecifies which domains the browser should send the cookie toSet as narrowly as possible. Using .example.com shares the cookie across all subdomains.
PathLimits the cookie to requests made to a specific path on the serverRestricts cookie scope to only the parts of the application that need it

Reading a Set-Cookie Header

A single Set-Cookie header can combine multiple attributes separated by semicolons. Here is a typical example for an authentication session cookie:

Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax; Max-Age=3600; Path=/

This sets a cookie named session_id that:

  • Cannot be read by JavaScript (HttpOnly)
  • Is only sent over HTTPS connections (Secure)
  • Is sent on top-level navigation but not in cross-site subresource requests (SameSite=Lax)
  • Expires one hour after it is created (Max-Age=3600)
  • Is only sent for requests to the root path and below (Path=/)

The HttpOnly Attribute

HttpOnly is one of the most important security attributes for any cookie that holds sensitive data. When this attribute is set, the browser refuses to expose the cookie to JavaScript. Code running on the page cannot read it through document.cookie, cannot access it through the Fetch or XMLHttpRequest APIs, and cannot exfiltrate it through any client-side mechanism.

This matters because cross-site scripting (XSS) attacks work by injecting malicious JavaScript into a page. If an attacker successfully injects a script, the first thing it typically attempts is reading the session cookie and sending it to a remote server. HttpOnly makes that impossible, breaking the most common XSS payload in a single attribute.

The Secure Attribute

The Secure attribute tells the browser to only include the cookie in requests sent over HTTPS. If a user visits your site over an unencrypted HTTP connection, whether due to a misconfiguration, a network attack, or a redirect issue, cookies marked Secure will not be transmitted. This prevents an attacker on the same network from intercepting the cookie through a man-in-the-middle attack.

For any production application, all session and authentication cookies should have the Secure attribute set. If your site forces HTTPS through an HTTP Strict Transport Security (HSTS) policy, the Secure attribute adds an additional layer of defence at the cookie level.

The SameSite Attribute

SameSite controls whether a cookie is included in requests that originate from a different website. This is the primary defence against Cross-Site Request Forgery (CSRF) attacks, where an attacker tricks a user's browser into making an authenticated request to your application from a malicious third-party page.

  • SameSite=Strict provides the strongest protection. The cookie is never sent with any cross-site request, including when a user clicks a link from an external site to your application. This can create a poor user experience because users arriving from external links will appear logged out until they navigate within your site.
  • SameSite=Lax is the recommended default for most applications. The cookie is sent when a user follows a top-level link to your site but is blocked on cross-site subresource requests such as images, scripts, and fetch calls embedded in third-party pages. This provides strong CSRF protection while keeping the login experience smooth.
  • SameSite=None disables same-site restrictions entirely. The cookie is sent with all cross-site requests. This is required for cookies that need to work across origins, such as those used in embedded iframes, single sign-on flows, or third-party widgets. It must always be combined with the Secure attribute, otherwise modern browsers will reject it.

Recommended Configuration for Session Cookies

For a session cookie used for authentication, these attributes should always be set together. Omitting any one of them leaves a specific and well-known attack vector open.

Set-Cookie: session=TOKEN; HttpOnly; Secure; SameSite=Lax; Path=/
  • HttpOnly: Essential. Prevents XSS scripts from reading and exfiltrating the token through JavaScript.
  • Secure: Essential. Ensures the token is never transmitted over an unencrypted connection.
  • SameSite=Lax: Recommended default. Provides solid CSRF protection without breaking normal navigation flows.
  • Path=/: Sends the cookie with all requests to the domain, which is appropriate for a global session token.
  • No Expires or Max-Age: Makes this a session cookie that is deleted automatically when the browser closes, which is appropriate for login sessions where you do not want persistence.

The Domain and Path Attributes

The Domain attribute specifies which hostnames the browser should include the cookie with. If you set Domain=example.com, the cookie is sent to example.com and all its subdomains such as api.example.com and auth.example.com. If you omit the Domain attribute entirely, the cookie is only sent to the exact hostname that set it, which is the more restrictive and generally safer default.

The Path attribute limits the cookie to a specific path on the server. A cookie with Path=/admin is only sent with requests to URLs that begin with /admin. This is useful for scoping cookies to the parts of your application that actually need them, reducing unnecessary exposure on other routes.

Frequently Asked Questions

  1. Can JavaScript read HttpOnly cookies?
    No, and that is exactly the purpose of the attribute. The browser sends HttpOnly cookies with every HTTP request automatically, but it never exposes them to document.cookie, the Fetch API, or any other client-side JavaScript interface. An attacker who successfully injects a script into your page cannot read HttpOnly cookies through that script.
  2. What happens if I set SameSite=None without the Secure attribute?
    Modern browsers will reject the cookie entirely and not store it. The combination of SameSite=None without Secure was declared invalid as part of browser security updates. If your application requires cross-site cookies, you must also serve them over HTTPS and include the Secure attribute.
  3. What is the difference between Expires and Max-Age?
    Expires sets an absolute date and time at which the cookie should be deleted, for example Expires=Thu, 01 Jan 2026 00:00:00 GMT. This can cause unexpected behaviour if the user's device clock is wrong. Max-Age sets the lifetime in seconds relative to the moment the cookie is created, which avoids clock skew entirely. Max-Age takes precedence over Expires if both are set, and it is generally the preferred choice for new applications.
  4. Should I set a Domain attribute on my cookies?
    Only if you specifically need the cookie to be shared across subdomains. If you omit the Domain attribute, the cookie is restricted to the exact hostname that set it, which is safer. Setting Domain explicitly broadens the scope and means the cookie will be sent to every subdomain, so only do this when your application architecture requires it.
  5. What is the difference between a session cookie and a persistent cookie?
    A session cookie has no Expires or Max-Age attribute. The browser stores it only in memory and deletes it when the browser session ends, typically when the window or tab is closed. A persistent cookie has an Expires date or Max-Age value and is written to disk, surviving browser restarts until it expires. For authentication, session cookies are more secure by default because they do not persist after the user closes their browser.

Conclusion

Cookie attributes are your first line of defence for protecting session data and preventing common web attacks. HttpOnly and Secure are non-negotiable for any authentication cookie. SameSite controls cross-site behaviour and is your primary tool against CSRF attacks. Domain and Path let you scope cookies precisely to avoid unnecessary exposure. Getting these attributes right is one of the simplest and most effective security improvements you can make to a web application. See also cookies vs sessions, XSS attacks, and CSRF attacks for a more complete picture of cookie-related security.