What do the `__Host-` and `__Secure-` name prefixes on an HTTP cookie mean, and what do browsers enforce when they see them?
answer
- name is the contract — attributes are not sent back
- `__Secure-` = Secure + HTTPS origin
- `__Host-` = Secure + no Domain + Path=/
- blocks subdomain cookie tossing
- browser drops the cookie silently if rules are broken
basics
~20 sThey are cookie-name conventions browsers enforce. __Secure- makes the browser reject the Set-Cookie unless it has the Secure attribute and came over HTTPS. __Host- adds two rules: no Domain attribute and Path=/, so the cookie is host-only and no subdomain can set it.
solid answer
~50 sBoth are magic prefixes on the cookie **name**, enforced by the browser when it parses Set-Cookie; if the rules are not met the cookie is dropped entirely. - `__Secure-name`: must carry `Secure` and be set from an HTTPS origin. - `__Host-name`: the same, **plus** `Path=/` and **no** `Domain` attribute, which makes it host-only — bound to exactly the host that set it, never sent to or settable by siblings or subdomains. The goal is integrity, not confidentiality. The `Cookie` request header carries only names and values, never attributes, so a server cannot normally tell whether `session=abc` was set host-only over HTTPS or injected by a compromised `evil.example.com` with `Domain=example.com` (cookie tossing / fixation). A `__Host-` name is a guarantee the browser vouches for. Use `__Host-` for session and CSRF cookies; use `__Secure-` when you genuinely need a `Domain=` cookie shared across subdomains.
code
http · 5 linesSet-Cookie: __Host-session=abc; Secure; Path=/; HttpOnly; SameSite=Lax
Set-Cookie: __Host-bad=abc; Secure; Path=/; Domain=example.com
Set-Cookie: __Host-bad2=abc; Secure; Path=/admin
Set-Cookie: __Secure-shared=abc; Secure; Path=/; Domain=example.com
Set-Cookie: __Secure-bad=abc; Path=/go deeper
Know that the prefix is part of the cookie name and that browsers enforce extra rules — Secure for __Secure-, plus host-only and Path=/ for __Host-.
Explain that attributes are not echoed in the Cookie header, so the name is the only trustworthy channel, and state all three __Host- conditions correctly.
Tie it to cookie tossing from a compromised or delegated subdomain and to insecure overwrite over plain HTTP; know the HTTPS-in-local-dev friction and how you handle it.
Frame it as a trust-boundary decision: __Host- per host versus __Secure- plus Domain= for SSO, and what admitting every subdomain into the session's trust boundary costs across the estate.
## Why prefixes exist When the browser sends cookies back it sends only name/value pairs: `Cookie: session=abc; theme=dark` Every attribute the server set — `Domain`, `Path`, `Secure`, `HttpOnly`, `SameSite`, expiry — is dropped. The server therefore has no way to know *how* a cookie it receives was scoped, or which host set it. Two attacks follow. **Cookie tossing / shadowing.** Cookies are scoped by host, not by origin, and scheme is largely ignored for scoping. If an attacker controls any subdomain of your registrable domain (an abandoned `old.example.com`, a customer-controlled `tenant.example.com`, an XSS on a marketing subdomain), they can send `Set-Cookie: session=attacker; Domain=example.com; Path=/`. The victim's browser now holds two `session` cookies and sends both; your server picks one and cannot distinguish them. **Insecure overwrite.** Even on an HTTPS site, a plaintext HTTP response for the same host (a stray link, an attacker on the network before HSTS kicks in) can set or overwrite a cookie. `Secure` prevents a cookie from being *sent* over HTTP, but historically not from being *written* over HTTP. Prefixes fix both by moving the guarantee into the name — the one thing that *is* transmitted back. ## The rules `__Secure-` prefix: the browser accepts the Set-Cookie only if the `Secure` attribute is present and the response came from a secure origin (HTTPS, or localhost). Otherwise the cookie is ignored silently — no error, no console failure in older engines. `__Host-` prefix: accepted only if all of these hold: - `Secure` is present and the origin is secure; - there is **no** `Domain` attribute (so the cookie is host-only); - `Path` is exactly `/`. Host-only is the important half. A host-only cookie for `app.example.com` is sent only to `app.example.com`; `evil.example.com` cannot write it, because writing it would require `Domain=example.com`, which the prefix forbids, and a bare host-only Set-Cookie from `evil.example.com` scopes to that host alone. Matching is case-sensitive and literal: `__Host-sid` works, `__host-sid` is just an ordinary name. ## How to use them Name the session cookie `__Host-session` and the CSRF cookie `__Host-csrf`. If you truly need one cookie across `app.example.com` and `api.example.com`, `__Host-` is impossible by definition — fall back to `__Secure-session` with `Domain=example.com`, and accept that every subdomain is now in your trust boundary. Operational caveats: prefixes need HTTPS, so local development over `http://` breaks unless you use `localhost` (treated as secure) or run TLS locally; make the prefix configurable per environment rather than stripping it in production by accident. Server frameworks generally treat the prefix as part of the name, so your read path must use the prefixed name too. And prefixes are enforced on write, not read — they do not stop an attacker from setting a *differently named* cookie, they only guarantee that a cookie that arrived under a prefixed name obeys the prefix rules. Prefixes are cheap, purely additive, and independent of `SameSite`; there is essentially no reason not to use `__Host-` for authentication cookies on a single host.
- An attacker controls old.example.com. How does naming the session cookie `__Host-session` stop them from overwriting the victim's session?To overwrite a cookie visible to app.example.com, old.example.com must set it with Domain=example.com. The `__Host-` prefix forbids any Domain attribute, so the browser rejects that Set-Cookie outright. A host-only cookie set by old.example.com stays scoped to old.example.com and is never sent to app.example.com.
- You need one login cookie shared by app.example.com and api.example.com. Which prefix can you use?Only `__Secure-`, because sharing across hosts requires Domain=example.com and `__Host-` forbids Domain. You still get the guarantee that the cookie was set over HTTPS with Secure, but you lose the anti-tossing property, so every subdomain of example.com is inside your trust boundary.
The Cookie header is an unsigned envelope with only a label inside. A prefix is a label the post office refuses to print unless the sender proved who they are — so the label itself becomes evidence.
saying these in an interview costs you the question
- Thinking the prefix is decoded or validated by the server rather than enforced by the browser
- Believing `__Host-` encrypts or hides the cookie value
- Setting `__Host-` together with Domain= and expecting it to work
- Assuming the server can read a cookie's Secure/Domain/Path attributes from the Cookie request header
- Claiming prefixes replace SameSite or CSRF tokens