Security Guide
MCP server cookie prefixes security — __Host- and __Secure- prefixes, subdomain cookie injection (cookie tossing), and SameSite comparison
Cookie prefixes are a browser-enforced mechanism that prevent a compromised subdomain from planting a forged session cookie on the main origin. Without cookie prefixes, an attacker controlling evil.skillaudit.dev can set Set-Cookie: session=attacker_token; Domain=skillaudit.dev and the victim's browser silently accepts it, replacing the legitimate session token. The __Host- prefix blocks this entirely: the browser rejects any cookie with this prefix that lacks Secure, Path=/, or that includes a Domain attribute. No subdomain can set a compliant __Host- cookie for another origin.
The cookie tossing attack
Domain-scoped cookies are shared across all subdomains. If your MCP server's session cookie is set as Set-Cookie: session=abc123; Domain=skillaudit.dev; Secure; HttpOnly, any subdomain of skillaudit.dev can also set a cookie named session with a different value and the same domain scope. Because the browser sends all matching cookies sorted by path specificity (most specific first) but otherwise in an unspecified order for same-specificity cookies, the attacker's token may appear before or interleaved with the legitimate token in the Cookie: header. The server reads the first matching cookie name and authenticates the attacker's session token.
This attack requires controlling a subdomain — a realistic scenario when MCP servers are hosted on multi-tenant platforms (e.g., customer.saas.dev), or when a subdomain hosts user-generated content, or when the subdomain's CDN origin is shared. The vulnerability requires no XSS and no CSRF — it is a straightforward cookie scope misuse.
__Host- prefix: the strongest defense
A cookie with the __Host- prefix is accepted by the browser only if ALL of the following are true:
- The
Set-Cookieheader includes theSecureflag - The
Set-Cookieheader specifiesPath=/ - The
Set-Cookieheader does NOT include aDomainattribute - The request was made over HTTPS
Without the Domain attribute, the cookie is bound to the exact host that set it. A cookie set by skillaudit.dev with no Domain attribute is only sent to skillaudit.dev — not to api.skillaudit.dev or any other subdomain. This eliminates subdomain-scoped injection entirely.
# Correct: __Host- session cookie Set-Cookie: __Host-session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/ # Browser rejects (has Domain attribute — defeats prefix purpose) Set-Cookie: __Host-session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/; Domain=skillaudit.dev # Browser rejects (missing Secure flag) Set-Cookie: __Host-session=abc123; HttpOnly; SameSite=Lax; Path=/ # Browser rejects (Path is not /) Set-Cookie: __Host-session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/api/
__Secure- prefix: minimum requirement
The __Secure- prefix requires only that the cookie be set over HTTPS with the Secure flag. It does NOT prevent the inclusion of a Domain attribute. This means a __Secure- cookie can still be domain-scoped and is therefore still vulnerable to cookie tossing from subdomains — but only from HTTPS subdomains, which raises the bar slightly. The main use case for __Secure- is when you need the cookie to be shared across subdomains (e.g., api.skillaudit.dev and skillaudit.dev) while still preventing the cookie from being set over HTTP.
# __Secure- prefix: still allows Domain attribute Set-Cookie: __Secure-session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/; Domain=skillaudit.dev
__Host- vs __Secure- vs unprefixed: comparison
| Property | No prefix | __Secure- | __Host- |
|---|---|---|---|
| Requires Secure flag | No | Yes (enforced) | Yes (enforced) |
| Requires HTTPS request | No | Yes | Yes |
| Domain attribute allowed | Yes | Yes | No (rejected) |
| Path must be / | No | No | Yes (enforced) |
| Subdomain injection possible | Yes | From HTTPS subdomains | No |
| Shared across subdomains | Yes (if Domain set) | Yes (if Domain set) | No (always host-only) |
| Use for session cookies | Never | Only if cross-subdomain needed | Yes — recommended |
Relationship to SameSite
SameSite controls whether a cookie is sent on cross-site requests (CSRF defense). Cookie prefixes control whether a cookie can be set by a subdomain with a forged domain scope (cookie tossing defense). They protect against different attack vectors and are complementary:
SameSite=Strict: cookie not sent on any cross-site request (strongest CSRF defense, breaks cross-origin navigation)SameSite=Lax: cookie sent on top-level navigation GETs but not on cross-origin subresource requestsSameSite=None; Secure: cookie sent on all requests (needed for cross-site embedded contexts)__Host-prefix: ensures the cookie cannot be tossed by a subdomain regardless of SameSite
A complete session cookie for an MCP server should combine both: __Host-session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/. This provides CSRF protection via SameSite and subdomain injection protection via the __Host- prefix.
Browser compatibility
Cookie prefixes are supported in all modern browsers: Chrome 49+, Firefox 50+, Safari 12+, Edge 17+. Internet Explorer does not support cookie prefixes. If your MCP client deployment must support IE (uncommon in 2026), prefixes should still be sent — they are silently ignored by IE, providing no protection there, but they still work correctly in all other browsers. The cookie is stored and sent without the prefix validation in IE, so IE users remain vulnerable to cookie tossing. This is an acceptable tradeoff if IE user population is negligible.
Legacy cookie jars — notably some older mobile WebViews and embedded browser contexts — may also ignore cookie prefixes. SkillAudit's audit report flags if the MCP server's client targets platforms with known prefix non-compliance.
SkillAudit findings for cookie prefix hygiene
__Host- or __Secure- prefix and with Domain= attribute — vulnerable to subdomain cookie injection (cookie tossing). Attacker controlling a subdomain can plant a forged session cookie. Score −20.__Secure- prefix but not __Host-; Domain= attribute present — still vulnerable to tossing from HTTPS subdomains. Upgrade to __Host- prefix if cross-subdomain sharing is not required. Score −12.__Host- prefix in Set-Cookie header but server also sets same-named cookie without prefix as fallback for legacy clients — attacker can set the unprefixed variant and shadow the prefixed session. Score −10.Run a SkillAudit scan on your MCP server to check cookie prefix usage across all Set-Cookie response headers, including those from authentication middleware that the MCP skill routes through.