Cookie attributes guide: SameSite, Partitioned, HttpOnly, Secure, Domain, Path, Priority

5 min read

Set-Cookie carries more than seven attributes, all of which interact with authentication, CSRF protection, and cross-site tracking enforcement. “Just set SameSite=Lax” or ”HttpOnly is enough” oversimplifies; with Partitioned arriving and third-party cookies dwindling, the right combination depends on use case. This article maps the attributes, then gives recommended combinations.

Attribute summary

Set-Cookie: sessionId=abc123; Domain=example.com; Path=/; Max-Age=3600;
            Secure; HttpOnly; SameSite=Lax; Priority=High; Partitioned
AttributeRoleDefault
DomainHostname scoperequest origin
PathPath scoperequest path
Expires / Max-AgeLifetimesession (cleared on tab close)
SecureHTTPS-only transmissionoff (sent over HTTP too)
HttpOnlyHidden from JSoff (visible to document.cookie)
SameSiteCross-site send rulesLax (modern browsers)
PartitionedCHIPS partitioningoff
PriorityEviction priorityMedium

SameSite: the CSRF and tracking dial

The most important attribute. Controls cross-site send behavior.

ValueCross-site GET (link)Cross-site POST (form)Inside iframe
Strict
Lax
None✓ (requires Secure)

SameSite=Lax (modern default)

Since Chrome 80 (2020), an unspecified SameSite is treated as Lax.

  • Same-site: always sent.
  • Cross-site top-level GET (<a href> click): sent.
  • Cross-site POST, iframe load, image load: not sent.

This is the primary CSRF defense — blocks “form POST from another site” attacks.

SameSite=Strict

Never sent on cross-site requests, including top-level GETs. A user clicking your site from a Google search arrives logged-out.

To preserve UX, the standard pattern is two cookies: a short-lived Strict cookie for sensitive operations and a long-lived Lax cookie for general session presence.

SameSite=None (requires Secure)

Sent in all cross-site contexts. Classic third-party cookie behavior.

Chrome 80+ rejects SameSite=None without Secure. HTTPS is mandatory.

Partitioned (CHIPS): replacement for third-party cookies

Set-Cookie: id=abc; Secure; SameSite=None; Partitioned

CHIPS (Cookies Having Independent Partitioned State) gives third-party iframes cookies that are partitioned per top-level site.

Motivation

Some third-party cookie use cases are legitimate: chat widgets keeping conversation state, embedded payment auth, CMS preview tokens. Cross-site tracking (“same cookie value identifies the same user across sites”) is the harm. CHIPS keeps the legitimate uses while breaking tracking:

  • chat.example.com iframe embedded on siteA.com → cookie stored under siteA’s partition.
  • Same iframe on siteB.comseparate partition.
  • chat.example.com cannot correlate users across siteA and siteB.

When to use

  • Your own embeddable widgets (chat, comments, payment iframes).
  • Legitimate cross-site state where tracking is not the goal.

If your cookie’s purpose is tracking, CHIPS doesn’t preserve the use case — you need First-Party Sets, Privacy Sandbox APIs, or a redesign.

HttpOnly and Secure

HttpOnly

Set-Cookie: sessionId=abc; HttpOnly
  • Cannot be read or written via document.cookie.
  • Sent on HTTP requests as normal.
  • The primary XSS defense for session cookies.

Always set HttpOnly on session IDs and auth tokens.

Secure

Set-Cookie: sessionId=abc; Secure
  • Sent only over HTTPS.
  • Prevents network interception of cookie values.
  • Mandatory with SameSite=None.

For dev (HTTP localhost) vs prod (HTTPS):

const secure = process.env.NODE_ENV === 'production';
res.cookie('sessionId', value, { secure, httpOnly: true });

Domain and Path

Domain

Set-Cookie: id=abc; Domain=example.com

The cookie is sent to example.com and all subdomains (api.example.com, www.example.com, …).

If omitted, the cookie is sent only to the exact host that set it (no subdomains). Specify a parent domain explicitly when you want subdomain sharing — and avoid otherwise to minimize the attack surface.

Path

Set-Cookie: id=abc; Path=/admin

Sent only on requests under /admin. /admin/users ✓, /dashboard ✗.

In practice most cookies use Path=/. Path scoping is occasionally used to reduce header bloat on cookie-heavy sites.

Expires and Max-Age

Set-Cookie: id=abc; Max-Age=3600
Set-Cookie: id=abc; Expires=Thu, 01 Dec 2026 16:00:00 GMT
UnitReference
Max-Agesecondsrelative to receipt time
ExpiresUTC datetimeclient’s clock

Max-Age wins when both are set. Prefer Max-Age to avoid client-clock-skew issues.

Max-Age=0 or a past Expires is the delete instruction — re-send with the same name / Domain / Path.

Priority (Chrome extension)

Set-Cookie: id=abc; Priority=High

Controls eviction order when the browser hits its cookie cap. Low / Medium (default) / High. Chrome-only; Firefox and Safari ignore it.

Rarely needed; useful when an auth cookie is being evicted on cookie-heavy sites.

Recommended combination for auth cookies

Set-Cookie: sessionId=abc;
            Path=/;
            Max-Age=3600;
            Secure;
            HttpOnly;
            SameSite=Lax
  • Path=/: site-wide.
  • Max-Age=3600: 1 hour, refreshable.
  • Secure: HTTPS only.
  • HttpOnly: XSS-resistant.
  • SameSite=Lax: CSRF-resistant.

Don’t set Domain unless you actually need subdomain sharing — leaving it off shrinks the attack surface.

Modern CSRF defense

SameSite=Lax alone has gaps:

  • Modifying methods (PUT / DELETE) cross-site → not sent under Lax. ✓
  • GET endpoints with side effects (legacy APIs) → sent under Lax. Vulnerable.
  • iframe-embedded apps → not sent under Lax. ✓

The robust complement is the Double Submit Cookie pattern: store the CSRF token in a cookie, require the client to also echo it in a header / form value. Server compares them:

// Server sets a CSRF cookie (not HttpOnly — JS needs to read it)
Set-Cookie: csrfToken=xyz; Secure; SameSite=Lax

// Client reads the cookie and echoes the value
fetch('/api/transfer', {
	headers: { 'X-CSRF-Token': getCsrfToken() }
});

Browser support differences

FeatureChromeFirefoxSafari
SameSite=Lax default
Partitioned (CHIPS)✓ (118+)✓ (131+)
Priority
Third-party cookie deprecationpausedoff by defaultoff by default (ITP)

Safari’s ITP (Intelligent Tracking Prevention) is the strictest; Partitioned is not yet implemented. Designs that depend on third-party cookies should assume Safari users will lose the feature and degrade gracefully.

Summary

Cookie attributes split into four axes: who receives it (Domain / Path / SameSite), how it’s protected (Secure / HttpOnly), when it expires (Max-Age / Expires), and partitioning (Partitioned). The 2026-standard auth cookie is Secure + HttpOnly + SameSite=Lax; for cross-site widgets, SameSite=None + Secure + Partitioned. Plan for graceful degradation on browsers that lack Partitioned, especially Safari.