Cookie attribute
< Set-Cookie: __Host-id=a3fWa; Secure; Path=/Cookie Prefixes: __Host- and __Secure- Rules
Cookie prefixes make the browser enforce attributes. The exact __Host- and __Secure- rules from RFC 6265bis, how to set them, and why a cookie vanishes.
- Without a prefix
- The browser applies no extra checks to the name
- Accepts
- __Secure- (needs Secure) or __Host- (Secure, Path=/, no Domain)
- Sent back to server
- Yes: the prefix is part of the cookie name
On this page
TL;DR: A cookie whose name starts with
__Host-is only accepted if it hasSecure,Path=/and noDomain, and was set over HTTPS.__Secure-only demandsSecureover HTTPS. The browser enforces this, so a subdomain or a network attacker cannot overwrite your session cookie.
The rules
From RFC 6265bis section 4.1.3 (still an Internet-Draft; it was in the RFC Editor queue when this page was last reviewed):
| Prefix | Secure attribute | Set from HTTPS | Domain attribute | Path attribute |
|---|---|---|---|---|
__Secure- | Required | Required | Allowed | Any |
__Host- | Required | Required | Forbidden | Must be / |
Set-Cookie: __Secure-theme=dark; Secure; Domain=example.com; SameSite=Lax
Set-Cookie: __Host-sid=a3fWa9; Secure; Path=/; HttpOnly; SameSite=Lax
If a Set-Cookie header with a prefixed name violates its rules, the browser discards the cookie. There is no error in the page and no Set-Cookie echo in document.cookie; the symptom is “the cookie never appears”. Server-side, the draft says a name starting with the case-sensitive string __Secure- implies the cookie was set with Secure. User agents must match the prefix case-insensitively, which prevents a mis-capitalized __host- name from dodging the checks while a server that folds case still reads it.
What problem prefixes solve
Cookies are scoped by host, not origin, and a cookie from evil.example.com with Domain=example.com is sent to app.example.com. If it has the same name as your session cookie, the browser may send both, and many frameworks read the first one. This is cookie tossing, and it feeds session fixation and CSRF-token overwrite. An HTTP-only network attacker can do the same by injecting a cookie into a plain HTTP response for your domain.
__Host-closes both holes. WithoutDomainthe cookie is host-only, so a sibling subdomain cannot set one that collides, andSecurestops the HTTP injection.Path=/stops a different path on the same host from planting one.__Secure-only closes the HTTP injection. It is for cookies that must span subdomains.
Prefixes are the right default for session and CSRF cookies. The Secure attribute alone leaves the subdomain case open.
Setting a __Host- cookie in common stacks
Express with express-session:
app.set('trust proxy', 1) // so req.secure is true behind a TLS-terminating proxy
app.use(session({
name: '__Host-sid',
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: { secure: true, httpOnly: true, sameSite: 'lax', path: '/' } // no domain
}))
Laravel reads these from config/session.php, with environment overrides:
SESSION_COOKIE=__Host-laravel_session
SESSION_SECURE_COOKIE=true
SESSION_PATH=/
SESSION_DOMAIN=null
SESSION_DOMAIN=null is what keeps Domain out of the header. If another layer, such as a CDN rule or a legacy middleware, appends Domain=, the cookie vanishes. From JavaScript the same restrictions apply: document.cookie = "__Host-flag=1; Secure; Path=/" works on HTTPS pages and is rejected on http://.
Debug checklist
- Run
curl -si https://example.com/login | grep -i set-cookieand look forDomain=andPath=on the__Host-line. - Behind a proxy, confirm the app sees HTTPS (
X-Forwarded-Proto); a framework that only addsSecurefor HTTPS requests will omit it, and the browser will drop the cookie. - Make sure every environment, including localhost, serves the cookie over HTTPS. Chrome and Firefox treat
http://localhostas secure; Safari has historically not. - Change the cookie name only with a migration plan: users with the old unprefixed cookie are logged out when you rename it.
Newer prefixes
MDN also documents __Http- (requires Secure and HttpOnly) and __Host-Http- (the __Host- rules plus HttpOnly). Its compatibility data lists them as supported from Chrome 140 and Firefox 143, and not in Safari. Use them as an addition where you can, not as a replacement for __Host-.
With Partitioned cookies
Partitioned cookies are recommended to use the __Host- prefix, so a third-party embed’s state is bound to its own host and partition.
Frequently asked questions
What does the __Host- cookie prefix require?
All three of these, or the browser rejects the cookie: a Secure attribute, a Path attribute of exactly /, and no Domain attribute. The cookie also has to be set from a secure (HTTPS) origin. The result is a cookie bound to one exact host that no sibling subdomain can overwrite.
What does the __Secure- prefix require?
Only that the cookie is set with the Secure attribute from a secure origin. It permits Domain, so it is the right choice for a cookie that must be shared across subdomains, though it gives weaker guarantees than __Host-.
Why is my __Host- cookie missing in the browser?
The browser silently drops a __Host- cookie that breaks any rule. The usual culprits are a Domain attribute added by a framework default, Path set to something other than /, a missing Secure flag because TLS terminates at a proxy, or the response arriving over plain HTTP. Check the Set-Cookie line in the Network panel.
Are cookie prefixes case-sensitive?
Servers should treat the prefix as case-sensitive, but the draft requires user agents to match it case-insensitively, so __host-id gets the same restrictions as __Host-id in a conforming browser. Use the exact spelling anyway.
Do prefixes work in all browsers?
Yes for __Secure- and __Host-. MDN compatibility data lists Chrome 49, Firefox 50 and Safari 13 as the first versions with support, so you can rely on them for any current audience. The newer __Http- and __Host-Http- prefixes are not supported in Safari.
Sources
Related
Secure
Learn how the Secure cookie attribute ensures cookies are only sent over HTTPS connections. Protect sensitive data from man-in-the-middle attacks.
Partitioned Cookies (CHIPS): The Partitioned Attribute
The Partitioned cookie attribute (CHIPS) gives third-party embeds a separate cookie jar per top-level site. Syntax, Secure requirement, and browser support.
Cookie Security: HttpOnly, SameSite, and Secure Flags
A comprehensive guide to understanding and implementing secure HTTP cookies to protect against XSS, CSRF, and session hijacking attacks.
Domain
Learn how the Domain cookie attribute controls which domains can access cookies. Understand subdomain sharing, security implications, and restrictions.