Re: _HttpOnly cookie prefix?

My concern is that with this approach, if we added a future prefix "Bla",
and a server sent a prefix of `__HostBlaHttpOnly`, then the "HttpOnly" part
would be ignored.

That plus the significantly more complex parsing (which we'd want both user
agents and servers to write parsing algorithms for) make me think that a
single char delimiter would be better.

In JS, a not-necessarily-efficient algorithm for parsing
`__Prefix_OtherPrefix-name` that would look something like this:
```
function getCookiePrefixes(cookieName) {
    if (cookieName.startsWith('__')) {
        // Ignore '__'
        const trimmedName = cookieName.slice(2);
        // Split the rest of the cookie name on '-'
        const parts = trimmedName.split('-');
        if (parts.length > 0) {
            // Split the prefixes part on '_'
            const prefixes = parts[0].split('_');
            return prefixes;
        }
    }
    return null;
}
```
Then the server can iterate over the prefixes, ignore any unknown ones (or
ones it doesn't care about) and ensure the ones it cares about are present.

On Tue, Jun 17, 2025 at 11:55 PM Rory Hewitt <rory.hewitt@gmail.com> wrote:

> OK, so a double-underscore to start, followed by a prefix (followed
> optionally by 1+ underscore+prefix 'pairs') followed by a dash followed by
> a user-defined string?
>
> Yeah, it would work, and it's certainly not awful, but I was hoping it
> would be doable *without* those extra underscores.
>
> In my opinion, "__UnpartitionedSecureHttp-myname" is significantly 'nicer'
> than "__Unpartitioned_Secure_Http-myname", even aside from being shorter.
> But others may disagree, obviously.
>
>  I guess I assumed the user-agent parsing could be as simple as this:
>
> if (cookiename.substr(0,1) == "__") {
>     prefixes == cookiename.substr(2);
>     dowhile (prefixes.substr(0,0) != "-") {
>         if (prefixes.substr(0,5) == "Secure") {
>             ...do Secure stuff...
>             prefixes == name.substr(6);
>         } elseif (prefixes.substr(0,3) == "Host") {
>             ...do Host stuff...
>             prefixes == name.substr(4);
>         } elseif (prefixes.substr(0,3) == "Http") {
>             ...do Http stuff...
>             prefixes == name.substr(4);
>         } elseif (prefixes.substr(0,10) == "Partitioned") {
>             ...do Partitioned stuff...
>             prefixes == name.substr(11);
>         } else {
>             ...unrecognized - find first dash and set prefixes to point to
> that...
>         }
>     }
> }
> ...do more stuff...
>
> (obviously I don't write code any more, and the above has all sorts of
> edge-cases, but in theory, adding a new prefix just means adding a new
> clause to the above dowhile loop. If a value is unrecognized, it's just
> ignored)
>
> I recognize it's probably not that simple, but it *could* be, no?
>
> Rory
>
> On Tue, Jun 17, 2025 at 2:05 PM Yoav Weiss <yoav.weiss@shopify.com> wrote:
>
>>
>>
>> On Tue, Jun 17, 2025 at 7:06 PM Rory Hewitt <rory.hewitt@gmail.com>
>> wrote:
>>
>>> > A potentially simpler/shorter option could be:
>>> __Host__HttpOnly-mycookie (where __HttpOnly__Host would work similarly, and
>>> we could also compound future prefixes as well, e.g.
>>> __Unpartitioned__HttpOnly).
>>>
>>> I raised this as a concern in a prior email several months ago:
>>>
>>> "I'm not sure how the various __Secure-* and __Host-* cookies would play
>>> with __HttpOnly-* cookies proposed by Yoav. Would this end up with cookie
>>> names like "__HttpOnly__Secure-string"?"
>>>
>>> I like Chris's idea of having a generic "__Prefixed{strings}" format,
>>> but surely the actual double-underscore is itself the prefix? do we need
>>> more than that?
>>>
>>> IOW, can't we simply define it as:
>>>
>>>     __{unordered-case-sensitive-prefixes}-{string}
>>>
>>> where {unordered-case-sensitive-prefixes} is one or more of the
>>> following *in any order*:
>>>
>>>     *Secure*
>>>     *Host*
>>>     *Http* (I prefer this to "HttpOnly', simply because for some
>>> reason we've gone for case-sensitive cookie names, and if we're talking
>>> CamelCase prefixes, then that can confuse things)
>>>     *Unpartitioned* (Chris's 'dummy' name)
>>>     ...more to come...
>>>
>>> So all of these would be equivalent:
>>>
>>>     __SecureHttpUnpartioned-myname
>>>     __HttpSecureUnpartioned-myname
>>>     __UnpartitionedSecureHttp-myname
>>>
>>
>> While I like the terseness and the smaller name, this would be harder to
>> parse correctly and efficiently.
>> It could also be an issue when it comes to forward compat, where
>> user-agents will not be able to ignore restrictions they don't yet support.
>>
>> Maybe introducing a single chat delimiter isn't awful?
>>
>> e.g. `__Host_Unpartitioned-name`
>>
>>
>>> This would require some tinkering to ensure that the current rules that
>>> apply to e.g. "__Secure-" and "__Host-" cookies can ensure that e.g. a
>>> cookie named "__HostSecureUnpartitioned-myname" can't be created with a
>>> Path prefix other than /, since that would clash with the existing "__Host"
>>> cookie definitions. And, of course, the existing double-underscore cookie
>>> naming would have to be ported in a backwards-compatible manner.
>>>
>>> The nice thing is that just using a double-underscore with 1+ unordered
>>> prefixes is simple and keeps the name of the cookie as small as possible.
>>>
>>> Rory
>>>
>>> On Mon, Jun 16, 2025 at 9:44 PM Yoav Weiss <yoav.weiss@shopify.com>
>>> wrote:
>>>
>>>> Thanks!
>>>>
>>>> On Mon, Jun 16, 2025 at 11:19 PM Chris Fredrickson <cfredric@google.com>
>>>> wrote:
>>>>
>>>>> This comment is orthogonal to this proposal (by which I mean, I don't
>>>>> intend to block the proposal on solving this), but I noticed that this
>>>>> proposal wants, in principle, to convey a single boolean signal in the
>>>>> cookie name (i.e. whether the cookie was marked HttpOnly or not). But due
>>>>> to the fact that prefixes don't compose well, Yoav was forced to create two
>>>>> new prefixes instead of one (and it would have been worse if the new
>>>>> prefixes didn't happen to require the Secure attribute).
>>>>>
>>>>> I think this shows the current prefix-based approach is hard to
>>>>> extend, and if we wanted to add another prefix (e.g. __Unpartitioned-, just
>>>>> off the top of my head), we'd actually have to add a handful of variants,
>>>>> due to the combinatorial explosion.
>>>>>
>>>>> I think this is solvable if we design a prefix system that's
>>>>> order-insensitive. My gut instinct is to want something like:
>>>>> __Prefixed(Host,HttpOnly,Unpartitioned)-mycookie
>>>>>
>>>>
>>>>> Some of those characters are forbidden in cookie names (which are
>>>>> tokens: https://datatracker.ietf.org/doc/html/rfc9110#name-tokens),
>>>>> though, so we could do something like this instead:
>>>>> __Prefixed!Host&HttpOnly&Unpartitioned!-mycookie
>>>>>
>>>>
>>>> A potentially simpler/shorter option could be:
>>>> __Host__HttpOnly-mycookie (where __HttpOnly__Host would work similarly, and
>>>> we could also compound future prefixes as well, e.g.
>>>> __Unpartitioned__HttpOnly).
>>>>
>>>>
>>>>> I realize there's going to be a lot of details to work out on this
>>>>> regarding backward compatibility, forward compatibility, security,
>>>>> particulars about the spelling, etc. But it might be nice to make the
>>>>> system more extensible now, rather than the next time someone tries to
>>>>> extend it.
>>>>>
>>>>> Curious if anyone else has thoughts!
>>>>>
>>>>
>>>
>>> --
>>> Rory Hewitt
>>>
>>> https://www.linkedin.com/in/roryhewitt
>>>
>>
>
> --
> Rory Hewitt
>
> https://www.linkedin.com/in/roryhewitt
>

Received on Wednesday, 18 June 2025 06:55:30 UTC