> draft

Cookie Domain

Zhong Yu, 2015-06-05

This article explains HTTP cookie domain policy, based on RFC_6265 and current browser behaviors.

Origin Domain

A website can set a cookie in a response; the cookie will be sent back to the same website in subsequent requests.

More precisely, if an HTTP client issues a request to a domain, and the response contains a valid cookie, the client should apply the cookie to subsequent requests to the same domain (subject to other constraints). We say the request domain is the origin domain of the cookie. A cookie is always applicable to its origin domain.

For example, cookie foo=bar originated from www.cats.com is applied to later requests to the same domain -

 request#0   GET http://www.cats.com:8080/abc HTTP/1.1

response#0   HTTP/1.1 200 OK
             Set-Cookie: foo=bar; Path=/; Expires=Sun, 02 Feb 2020 00:00:00 GMT
       ...

 request#n   GET https://www.cats.com/xyz HTTP/1.1
             Cookie: foo=bar

Note that the port number doesn't matter here; the scheme(http/https) doesn't matter either (unless cookie's Secure attribute is set). In the example above, the cookie originated from http://www.cats.com:8080 is applicable to request to https://www.cats.com:443 as well, even though the schemes and ports are different.

If the request host is an IP address, e.g. 127.0.0.1, we say, for the purpose of this article, that the origin domain is the IP.

Cover Domain

A cookie can have the "Domain" attribute set to a valid domain name, which we call the cover domain of the cookie. If the "Domain" attribute is not set, we say the cover domain is null.

If cover domain is null, a cookie is only applicable to its origin domain. For example, a cookie from www.cats.com is not applicable to cats.com, and vice versa, if cover domain is null.

If cover domain is set, a cookie is applicable to the cover domain and all its subdomains. For example

 request#0   GET http://foo.www.cats.com/ HTTP/1.1

response#0   HTTP/1.1 200 OK
             Set-Cookie: foo=bar; Path=/; Domain=cats.com

the cover domain is cats.com, therefore the cookie is applicable to cats.com, x.cats.com, x.y.cats.com, etc.

The cover domain must cover the origin domain, that is, the cover domain must be the same as, or a parent of, the origin domain. In the example above, the origin domain is foo.www.cats.com, therefore the cover domain could only be set to foo.www.cats.com, www.cats.com, or cats.com (but not "com", see next section).

If the origin domain is an IP, the cover domain must be null. A cookie with an IP origin is only applicable to that IP.

A cover domain should not contain a leading dot, like in .cats.com; if it does, the client should remove the leading dot.

If a cookie's cover domain is set illegally or incorrectly, the client should ignore the cookie entirely.

On a related matter, a cookie's identity is defined by the triplet (name, domain, path), of which domain is either the cover domain if it's set, or the origin domain otherwise. This needs to be noted when replacing or deleting a cookie.

Public Suffix

Obviously, we cannot allow a cover domain to be "com", otherwise, a cookie from cats.com could be sent to dogs.com, causing problems. A cover domain must not be a public suffix.

A public suffix is a domain under which the general public can register direct subdomains. For example, "com", "org", "uk", "co.uk" are public suffixes. Direct subdomains of a public suffix belong to different owners, therefore their cookies should not mingle, and that's why a public suffix cannot be allowed as cover domain.

A private company can also offer a domain as a public suffix. For example, when you lease a server from Amazon AWS, a domain name is assigned to it, e.g. foo.compute.amazonaws.com. You "own" this domain in the sense that its usage is at your discretion. Someone else may own a sibling bar.compute.amazonaws.com. To prevent bar from sending cookies to foo, the domain compute.amazonaws.com is listed as a public suffix.

The complete list of public suffixes is maintained at https://publicsuffix.org. In addition, we recommend that

These two bullet points cannot be derived from the texts of RFC_6265 and publicsuffix.org; instead, they are concluded from current behaviors of major browsers. Other client and server implementers should follow these behaviors too. It's a simplified and conservative approach for dealing with subtleties of public suffix. See next section for a more complicated narrative.

Summary of rules from above:

More on Public Suffix

According to RFC_6265, if a cookie's cover domain is a public suffix,

The first clause looks odd, but it permits a public suffix domain (if it ever resolves to an HTTP server) to specify itself as the cover domain, while making sure the cookie will not propagate to subdomains. Presumably, this clause is for backward compatibility of some existing websites on public suffix domains. However, the only major browser that currently implements this clause is Firefox; all other major browsers simply reject such cookies. Therefore in the previous section, to follow the browser consensus, we reject this case as well - a cover domain cannot be a public suffix, regardless of the origin domain.

Another problem - RFC_6265 does not properly handle the situation where a public suffix has a parent that is not a public suffix; such situation probably didn't exist when the RFC was written. Strictly following the texts of the RFC, a client would allow foo.compute.amazonaws.com to set a cookie's cover domain to amazonaws.com, and the cookie would be applicable to bar.compute.amazonaws.com. This behavior is clearly undesired.

Fortunately, no major browser behaves that way; however, browsers handle the case differently. Safari appears to simply treat amazonaws.com as a public suffix, rejecting all cookies with it as cover domain. In the previous section, we follow this simple approach, rejecting any parent of public suffix as cover domain.

On the other hand, Firefox and Chrome take a more sophisticated approach, allowing amazonaws.com as cover domain in some cases (e.g. when the origin domain is www.amazonaws.com) while making sure those cookies do not propagate below compute.amazonaws.com. This approach is better; however, Amazon cannot really rely on it to share cookies, because not all browsers support the approach.

These discussions intend to justify the conservative approach we laid out in the previous section.

Nevertheless, it would be interesting to discuss what is the "ideal" way to handle public suffixes in cookie handling -

The domain amazonaws.com is not really a public suffix, because its direct subdomains are not open to the public; instead, they are all controlled by Amazon. It doesn't really hurt if www.amazonaws.com and zzz.amazonaws.com, or even compute.amazonaws.com, share cookies though domain amazonaws.com - as long as these cookies do not propagate downwards across public suffix compute.amazonaws.com, reaching user websites. At the same time, we must not allow a user website under compute.amazonaws.com to set a cover domain to amazonaws.com, interfering with Amazon's websites.

With that in mind, the next section defines a more sensible model for cookie domain policy.

Coverage Model

A cover domain's coverage is the set of domains that the cookie is applicable to; the set is defined by:

That is, the coverage starts from the domain, propagates downwards, stopped at public suffix nodes.

The coverage is tested when receiving and sending the cookie, in a symmetric way

Return to the Amazon example,

Here's a pseudo code for getting the list of cover domains that cover a given request_domain

    list.add(request_domain)
    for each parent of request_domain, ordered from longest to shortest
        if parent is a public suffix
            break loop
        list.add(parent)

Contact: bayou-io@googlegroups.com