Intent to Implement: Cookie Prefixes

174 views
Skip to first unread message

Mike West

unread,
Oct 9, 2015, 6:26:55 AM10/9/15
to blink-dev, Adam Barth, est...@chromium.org, Ryan Sleevi
+BCC: net-dev@, security-dev@

# Contact emails

# Spec
https://tools.ietf.org/html/draft-west-cookie-prefixes-01 # Summary This feature adds a set of restrictions upon the names which may be used for cookies with specific properties. These restrictions enable user agents to smuggle cookie state to the server within the confines of the existing "Cookie" request header syntax, and limits the ways in which cookies may be abused.

In a nutshell: `$Secure-*` cookies have to have the `Secure` flag, and `$Origin-*` cookies have to have `Path=/`, can't have `Domain`, and might require `Secure` (depending on the setter).

This seems like the simplest thing that might possibly work.

# Motivation
Cookies are terrible. This proposal _might_ make them slightly less terrible, by addressing the "Weak Confidentiality" and "Weak Integrity" concerns spelled out in RFC 6265.

The syntax is fairly hideous, but practical: 

* No new behavior is defined; the spec is predicated upon enforcement of existing flags.

* No new syntax is defined; the spec is completely backwards compatible.

* No server needs to change anything other than the name of the cookie it sets. Browsers that support the feature will enforce existing flags, browsers that don't support the feature won't.

* The client-side changes to perform the validation checks are fairly small.

# Compatibility Risk
The syntax is completely backwards compatible with the existing cookie syntax and flags. Worst case, we roll all the code back, and the status quo prevails. The only thing we'd lose in that case are the extra guarantees the prefix would provide.

Mozilla folks are cautiously interested, calling the scheme "ugly, but clever" (https://twitter.com/dveditz/status/652228007910764544).
Edge and Safari haven't said anything (which is understandable, since I only shared the spec yesterday).
Web developers are cautiously interested:

* Eric Lawrence has been pushing for this for a million years.
* Dropbox says they'd probably use it (https://twitter.com/frgx/status/651793265285443584)
* Other folks are concerned about stomping on existing cookies (https://twitter.com/mikesherov/status/652091574248210432) (which I think we can easily mitigate by measuring cookie names and picking an unused prefix), and Ryan suggested that it might be bad precedent to set (https://twitter.com/sleevi_/status/652387624548704256) (which I think we can head off by pointing to the fact that this proposal adds zero _new_ functionality that isn't already covered in the spec).

*shrug* I think it's well worth experimenting with.

# Ongoing technical constraints
We can't implement this on iOS because we don't have control over either the cookie store or the network stack.

# OWP launch tracking bug

# Link to entry on the Chrome Platform Status
https://www.chromestatus.com/features/4952188392570880

# Requesting approval to ship
No. I proposed this yesterday, it might be completely nuts. CCing abarth@, who probably can explain why that might be the case. :)

-mike

PhistucK

unread,
Oct 9, 2015, 7:15:10 AM10/9/15
to Mike West, blink-dev, Adam Barth, est...@chromium.org, Ryan Sleevi
Two rather off-topic comments -
- I thought the network stack is about the only thing Chrome does control on iOS. I am probably misremembering, but are you sure about that?
- This intent template is missing the "Will this be supported on all 6 Blink platforms..." question.
 - Is that intentional?
 - Did you remove it?
 - If the answer is a double "no", can you provide the steps that got to this template?

Thank you!


PhistucK

--
You received this message because you are subscribed to the Google Groups "net-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to net-dev+u...@chromium.org.
To post to this group, send email to net...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/net-dev/CAKXHy%3Dd-n3sWjL%2Bq1MB6QQZgktGhqRzSqnj93xAJ6KshGhrhYw%40mail.gmail.com.

Mike West

unread,
Oct 9, 2015, 8:44:38 AM10/9/15
to PhistucK, blink-dev, Adam Barth, est...@chromium.org, Ryan Sleevi
On Fri, Oct 9, 2015 at 1:14 PM, PhistucK <phis...@gmail.com> wrote:
Two rather off-topic comments -
- I thought the network stack is about the only thing Chrome does control on iOS. I am probably misremembering, but are you sure about that?

My (very) vague understanding is that WKWebView makes this more difficult.

- This intent template is missing the "Will this be supported on all 6 Blink platforms..." question.
 - Is that intentional?
 - Did you remove it?
 - If the answer is a double "no", can you provide the steps that got to this template?

I probably deleted it while reformatting. Certainly not intentional: this would be available on every Blink platform.

-mike

Elliott Sprehn

unread,
Oct 9, 2015, 1:02:20 PM10/9/15
to Mike West, Adam Barth, est...@chromium.org, blink-dev, Ryan Sleevi

It seems like the Secure flag wasn't added that long ago, why can't we add more flags?

The prefixes seem super ugly, and you can't combine them so the syntax is not very extensible. Is there a reason to not limit this to HttpOnly cookies?

I wonder if instead of prefixes just using an extra cookie with the special flags would be better, Cookie-Flags=CookieName1=FlagA FlagB, CookieName2=Flag FlagD. That would also let you do something like Cookie-Flags-Default=FlagC to force a specific flag on all cookies.

David Benjamin

unread,
Oct 9, 2015, 1:21:06 PM10/9/15
to Elliott Sprehn, Mike West, Adam Barth, est...@chromium.org, blink-dev, Ryan Sleevi
I like this idea! It's kinda ugly, but does the job.

I would probably drop the $Origin half instead say $Origin requires the Origin flag from draft-west-origin-cookies-01. There are other weird bits re cookies and same-origin like ignoring the port, so I think it should require that. Basically this is a solution to the downgrade problems in section 5.2.

(Though one downside with $Origin- over the separate header is that we use more bandwidth if there's lots of different cookies. But the separate header has downgrade problems unless we always send the Origin-Cookies header which is itself a bandwidth concern. :-/ )

On Fri, Oct 9, 2015 at 1:02 PM 'Elliott Sprehn' via blink-dev <blin...@chromium.org> wrote:

It seems like the Secure flag wasn't added that long ago, why can't we add more flags?

The prefixes seem super ugly, and you can't combine them so the syntax is not very extensible. Is there a reason to not limit this to HttpOnly cookies?

I wonder if instead of prefixes just using an extra cookie with the special flags would be better, Cookie-Flags=CookieName1=FlagA FlagB, CookieName2=Flag FlagD. That would also let you do something like Cookie-Flags-Default=FlagC to force a specific flag on all cookies.

To avoid downgrade problems, we'd have to always send the Cookie-Flags header on every cookied request, whether the site pays attention to it or not. (Otherwise we're indistinguishable from a browser that doesn't implement this.) If we're okay with that, that works too. People seem to be hesitant to add new headers sent on all requests though.

Though I think we actually don't want it extensible (like the concern about precedent for crazier prefixes like $SSO- in the future). Same-origin is our security policy, so this just should be seen as a bandaid for all the ways cookies fail to honor same-origin. So we get to draft-west-origin-cookies-01 (minus the separate header now) + $Origin or Cookie-Flags Origin, and then we stop there.

IMO, the only reason to do $Secure (and I think that is worthwhile) is just so that existing uses of cookies can plug the http/https hole without rearchitecting everything.

David Benjamin

unread,
Oct 9, 2015, 1:51:36 PM10/9/15
to Elliott Sprehn, Mike West, Adam Barth, est...@chromium.org, blink-dev, Ryan Sleevi
I suppose, for completeness, $HttpOnly is also potentially a prefix we would want, and then being able to combine flags is now more of a big deal. Though I've always seen the HttpOnly flag as a sort of an odd relic, so I think it's fine ignoring that if that becomes the only reason we don't like this solution. We are otherwise very consistent about assuming that any JS running inside an origin gets to act on behalf of that origin. A threat model where the attacker gets to run arbitrary JS in your origin but not read (and now modify) some subset of cookies is slightly odd. (Like I think they can still CSRF you all they like.)

Emily Stark

unread,
Oct 9, 2015, 3:54:50 PM10/9/15
to David Benjamin, Elliott Sprehn, Mike West, Adam Barth, Emily Stark, blink-dev, Ryan Sleevi

On Fri, Oct 9, 2015 at 1:20 PM David Benjamin <davi...@chromium.org> wrote:
I like this idea! It's kinda ugly, but does the job.

I would probably drop the $Origin half instead say $Origin requires the Origin flag from draft-west-origin-cookies-01. There are other weird bits re cookies and same-origin like ignoring the port, so I think it should require that. Basically this is a solution to the downgrade problems in section 5.2.

(Though one downside with $Origin- over the separate header is that we use more bandwidth if there's lots of different cookies. But the separate header has downgrade problems unless we always send the Origin-Cookies header which is itself a bandwidth concern. :-/ )

On Fri, Oct 9, 2015 at 1:02 PM 'Elliott Sprehn' via blink-dev <blin...@chromium.org> wrote:

It seems like the Secure flag wasn't added that long ago, why can't we add more flags?

How would adding a flag work? It seems to me that an attacker could always set the cookie initially without the flag, thereby defeating the point. 

The prefixes seem super ugly, and you can't combine them so the syntax is not very extensible. Is there a reason to not limit this to HttpOnly cookies?

I wonder if instead of prefixes just using an extra cookie with the special flags would be better, Cookie-Flags=CookieName1=FlagA FlagB, CookieName2=Flag FlagD. That would also let you do something like Cookie-Flags-Default=FlagC to force a specific flag on all cookies.

To avoid downgrade problems, we'd have to always send the Cookie-Flags header on every cookied request, whether the site pays attention to it or not. (Otherwise we're indistinguishable from a browser that doesn't implement this.) If we're okay with that, that works too. People seem to be hesitant to add new headers sent on all requests though.

I'm not sure I understand the Cookie-Flags proposal. Is the idea that the browser sends Cookie-Flags to tell the server what the flags on the cookies are, and the server checks the flags to be sure they are as expected? That seems like more work on the server's part and a lot more likely for the developer to get it wrong. The developer would have to parse the flags and remember to check them on any given cookie before using it, right? (And to distinguish unexpectedly empty Cookie-Flags [something funky going on] from Cookie-Flags not present [unsupported browser], etc.)
 

Though I think we actually don't want it extensible (like the concern about precedent for crazier prefixes like $SSO- in the future). Same-origin is our security policy, so this just should be seen as a bandaid for all the ways cookies fail to honor same-origin. So we get to draft-west-origin-cookies-01 (minus the separate header now) + $Origin or Cookie-Flags Origin, and then we stop there.

IMO, the only reason to do $Secure (and I think that is worthwhile) is just so that existing uses of cookies can plug the http/https hole without rearchitecting everything.

+1, I think it's the rare case of a hacky band-aid that's only worth doing because it's so ridiculously simple.

David Benjamin

unread,
Oct 9, 2015, 4:05:22 PM10/9/15
to Emily Stark, Elliott Sprehn, Mike West, Adam Barth, blink-dev, Ryan Sleevi
On Fri, Oct 9, 2015 at 3:54 PM Emily Stark <est...@chromium.org> wrote:
The prefixes seem super ugly, and you can't combine them so the syntax is not very extensible. Is there a reason to not limit this to HttpOnly cookies?

I wonder if instead of prefixes just using an extra cookie with the special flags would be better, Cookie-Flags=CookieName1=FlagA FlagB, CookieName2=Flag FlagD. That would also let you do something like Cookie-Flags-Default=FlagC to force a specific flag on all cookies.

To avoid downgrade problems, we'd have to always send the Cookie-Flags header on every cookied request, whether the site pays attention to it or not. (Otherwise we're indistinguishable from a browser that doesn't implement this.) If we're okay with that, that works too. People seem to be hesitant to add new headers sent on all requests though.

I'm not sure I understand the Cookie-Flags proposal. Is the idea that the browser sends Cookie-Flags to tell the server what the flags on the cookies are, and the server checks the flags to be sure they are as expected? That seems like more work on the server's part and a lot more likely for the developer to get it wrong. The developer would have to parse the flags and remember to check them on any given cookie before using it, right? (And to distinguish unexpectedly empty Cookie-Flags [something funky going on] from Cookie-Flags not present [unsupported browser], etc.)

If we were to go with this one, I imagine it would want to be implemented by the web framework (they already have to parse the Cookie header and probably developers aren't doing that themselves).

Though, yeah, that does require that their library implement it for them. That $Secure- (and later $Origin- when/if origin cookies exist) doesn't need modifications to the HTTP library is definitely nice.

David

Emily Stark (Dunn)

unread,
Oct 9, 2015, 4:14:14 PM10/9/15
to David Benjamin, Emily Stark, Elliott Sprehn, Mike West, Adam Barth, blink-dev, Ryan Sleevi
On Fri, Oct 9, 2015 at 10:05 PM, David Benjamin <davi...@chromium.org> wrote:
On Fri, Oct 9, 2015 at 3:54 PM Emily Stark <est...@chromium.org> wrote:
The prefixes seem super ugly, and you can't combine them so the syntax is not very extensible. Is there a reason to not limit this to HttpOnly cookies?

I wonder if instead of prefixes just using an extra cookie with the special flags would be better, Cookie-Flags=CookieName1=FlagA FlagB, CookieName2=Flag FlagD. That would also let you do something like Cookie-Flags-Default=FlagC to force a specific flag on all cookies.

To avoid downgrade problems, we'd have to always send the Cookie-Flags header on every cookied request, whether the site pays attention to it or not. (Otherwise we're indistinguishable from a browser that doesn't implement this.) If we're okay with that, that works too. People seem to be hesitant to add new headers sent on all requests though.

I'm not sure I understand the Cookie-Flags proposal. Is the idea that the browser sends Cookie-Flags to tell the server what the flags on the cookies are, and the server checks the flags to be sure they are as expected? That seems like more work on the server's part and a lot more likely for the developer to get it wrong. The developer would have to parse the flags and remember to check them on any given cookie before using it, right? (And to distinguish unexpectedly empty Cookie-Flags [something funky going on] from Cookie-Flags not present [unsupported browser], etc.)

If we were to go with this one, I imagine it would want to be implemented by the web framework (they already have to parse the Cookie header and probably developers aren't doing that themselves).
 
Though, yeah, that does require that their library implement it for them. That $Secure- (and later $Origin- when/if origin cookies exist) doesn't need modifications to the HTTP library is definitely nice.

Yeah, in my mind, whether it's the library/framework or the developer doesn't make much difference, we'll end up with a gajillion buggy implementations regardless. (Plus I imagine that even if the developer isn't doing the parsing, they still have to be the one who remembers to check the flags whenever the cookie is read, which could also be somewhat error-prone.)

Mike West

unread,
Oct 12, 2015, 10:31:23 AM10/12/15
to Emily Stark (Dunn), David Benjamin, Emily Stark, Elliott Sprehn, Adam Barth, blink-dev, Ryan Sleevi
Hey folks! Glad there's interest in the proposal. A few things before the line-by-line:

1. Eric Lawrence posted http://textslashplain.com/2015/10/09/duct-tape-and-baling-wirecookie-prefixes/, explaining some of the motivations of his original proposal. I think it's worth skimming for background.

2. I've poked at the spec a bit based on some conversations. https://tools.ietf.org/html/draft-west-first-cookie-prefixes-03 now limits the new behaviors to secure origins (so that a prefixed cookie set from a non-secure origin is rejected entirely), which simplifies things a bit.

On Fri, Oct 9, 2015 at 10:13 PM, Emily Stark (Dunn) <est...@google.com> wrote:
On Fri, Oct 9, 2015 at 10:05 PM, David Benjamin <davi...@chromium.org> wrote:
On Fri, Oct 9, 2015 at 3:54 PM Emily Stark <est...@chromium.org> wrote:
The prefixes seem super ugly, and you can't combine them so the syntax is not very extensible. Is there a reason to not limit this to HttpOnly cookies?

The draft addresses the two scenarios I see as the biggest holes in cookies' current model. As David notes elsewhere in the thread, the threat model of HttpOnly is strange, and I'm not sure it's terribly valuable. Also, I plan on giving folks the ability to lock down `document.cookies` as part of CSP (https://w3c.github.io/webappsec-csp/cookies/ currently only contains the writing bits, I plan to add reading bits as well), so I hope to address that strange threat model in a different way.

I wonder if instead of prefixes just using an extra cookie with the special flags would be better, Cookie-Flags=CookieName1=FlagA FlagB, CookieName2=Flag FlagD. That would also let you do something like Cookie-Flags-Default=FlagC to force a specific flag on all cookies.

I'm sure we could find a syntax for the field's payload that made sense, so `Cookie-Fields` is certainly a viable option. I agree with Emily's assessment, however: this is more work for the developer, and substantially more complicated than "This cookie has a name that it can't possibly have unless it was set securely." The latter doesn't require any code change on the server-side other than the name of the cookie.

It is ugly. Like, really ugly. But there's precedent in the set of "forbidden header names"'s "sec-" prefix that XHR and Fetch don't have access to.

*shrug* This seems like a tiny thing that we can do which a) is trivial to implement both inside Chromium and on the server side, b) is based entirely on existing functionality, so doesn't require additional explanation, and c) doesn't open the floodgates to larger modifications to cookies.

Note: I think cookies are fairly terrible and should be burned down and replaced, but, realistically, that's not going to happen in the forseeable future. This is something we could ship tomorrow without breaking The Internets. :)

-mike
Reply all
Reply to author
Forward
0 new messages