Seems like every time I look at cookies they've grown a new wrinkle. They're just a nightmare to keep up with.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#co...
> For more information about cookie prefixes and the current state of browser support, see the Prefixes section of the Set-Cookie reference article.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Se...
(Cookie prefixes have been widely supported since 2016 and more or less globally supported since 2019.)
They’re backwards-compatible, so if your cookie need meets the requirements for the `__Host-` prefix, you should use `__Host-`.
The only recent large problem with cookies were to changes to avoid CSRF, those were opt-out, but they were also extremely overdue.
All of the web standards are always gaining new random features. You don't have to keep-up with most of them. They do look like bad abstractions, but maybe it's just the problem that is hard.
If you are in complete control of front-end and back-end it's not a big problem, but as soon as you have to get different stuff to interoperate it gets very stupid very fast.
Firefox accepts five characters which RFC recommends that servers not send:
0x09 (horizontal tab)
0x20 (spaces)
0x22 (double quotes)
0x2C (commas)
0x5C (backslashes)
I agree with at least some of these. Cookies without commas? Quotes?> cookie-value = cookie-octet / ( DQUOTE cookie-octet DQUOTE )
> Per the grammar above, the cookie-value MAY be wrapped in DQUOTE characters. Note that in this case, the initial and trailing DQUOTE characters are not stripped. They are part of the cookie-value, and will be included in Cookie header fields sent to the server.
As for why that is, I have no idea.
This one just happens to have been owned and maintained by core Rust folks and used in a lot of larger libraries. This is more the exception than the rule.
It's a given that you should do due diligence on crates and not just use the first name that matches your use case. There's a lot of crate name squatting and abandonware.
Rust crates need namespacing to avoid this and similar problems going forward.
> I enjoyed visiting Tokio (Tokyo) the city and I liked the "io" suffix and how it plays w/ Mio as well. I don't know... naming is hard so I didn't spend too much time thinking about it.
https://www.reddit.com/r/rust/comments/d3ld9z/comment/f03lnm...
From the original release announcement of tokio on r/rust on Reddit.
And also to the sibling commenter, if tokio is a problematic name to you:
Would either of the following names be equally problematic or not?
- Chicago. Code name for Windows 95, and also the name of a city in the USA. https://en.wikipedia.org/wiki/Development_of_Windows_95 https://en.wikipedia.org/wiki/Chicago
- Oslo. Name of a team working on OpenStack, and also appears in their package names. Oslo is the capital of Norway. https://wiki.openstack.org/wiki/Oslo https://en.wikipedia.org/wiki/Oslo
If yes, why? If no, also why?
Big tech uses them instead of wasting legal time and money having to clear a new name that's temporary or non-public.
Changing the name to Tokio removes this benefit and still leaves it disconnected from its purpose.
see also, e.g. Tokio Hotel
https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
That has me thinking of Neutral Milk Hotel. Totally different vibes.
I don't think that's the case. Amazon, Nokia as some counterexamples.
It hasn't been implemented despite crowd demanding it on HN for years because it won't solve the problem (namespace squatting is going to replace name squatting and tada! you're back to square one with an extra step).
That's the main problem with “just add namespace FFS” discussions that come every other week: everyone has its own vision of what namespace should look like and what they are meant for, but nobody has ever taken the time to write an RFC with supporting arguments. In fact, people bring this mostly in ways that are related to name squatting (like right here) even though that's not a problem namespace can solve in the first place. It's magical thinking at its finest.
https://rust-lang.github.io/rfcs/3243-packages-as-optional-n...
This isn't the kind of namespace people say they want to prevent squatting.
But once you know a namespace is owned by a company or project, you can know that everything under it is legit. Which solves the vast majority of squatting and impersonation problems.
Also you know that everything under "node" for example is part of the language.
There's a way to solve it partially: you can have a special part of your namespace tied to domains and require that eg com.google.some-package be signed by a certificate that can also sign some-package.google.com
Of course, there's no guarantee that https://company.com belongs to the company, but the public has already developed ways of coping with that.
(I specifically suggest doing that only to part of your namespace, because you still want people to be able to upload packages without having to register a domain first.)
Keep in mind that the majority of package by far don't come from companies in the first place, and requiring individual developers to have a domain of their own isn't particularly welcoming.
It's going to be tons of complexity for zero actual benefit.
But its authors rightly concluded that it's useless to expect to prevent name squatting by any technical mean!
And it doesn't have to be the direct domain+path of the repository, it can be some URL where you put a metadata file that points to the source repo.
Or to be slightly more serious avoid calling it a cookie and call it something else. Too much baggage surrounding the word cookie.
You graduate from consuming cookies to eating...
https://chefjar.com/wp-content/uploads/2021/05/popeyes-biscu...
Is that generally true of scones?
At least for some use cases. Of course, it doesn't directly integrate with headers.
On the other hand; the size constraints on storage will be less severe than those on tags in each http request, so perhaps this is being overly clever with risks of accidentally huge payloads suddenly being sent along with each request.
Could you point me to more reading about this? It's the first time I've heard of it
This could have a huge advantage, because if you leave the original service untouched on port 80/443, there is no alert popping up on the defending blueteam side.
This gives me an idea for a project...
we're stuck with cookies because they exist.
Being anti-ads is a valid opinion. It has less intellectual cover than pro “privacy” though.
I spend a solid month chasing ghosts around iOS Safari arbitrarily eating cookies from domains controlled by our customers. I've never seen Google/Twitter/Facebook/etc domains lose session state like this.
I had hoped when writing this article that Google would look at Safari and see that it was always strict about feel comfortable about changing to be the same. But doing so now would unfortunately break too many things for too many users.
Doing otherwise will require cooperation to adjust on the specificities clients expect, and you fall into the trap of the prisoner dilemna.
Being liberal on what you accept is a path for disaster.
Sure, protocol should be designed to be as specific as possible but unfortunately these are not always defined up to that point for any good or bad reasons, and we generally are at best just in the implementation side and cannot influence the writing of the protocol, so the Postel's law is the best we can apply to avoid having to cooperate with the rest of the planet.
As they should. Postel's Law was a terrible idea and has created minefields all over the place.
Sometimes, those mines aren't just bugs, but create gaping security holes.
If your client is sending data that doesn't conform to spec, you have a bug, and you need to fix it. It should never be up to the server to figure out what you meant and accept it.
Anyhow, I can't say I'm thrilled that some deeply nested subtree of divs for instance might be closed by a open-button tag just because they were themselves part of a button, except when... well, lots of exceptions. It's what we have, I guess.
It's also not a (fully) solved problem; just earlier this year I had to work around an issue in the chromium html parser that caused IIRC quadratic parsing behavior in select items with many options. That's probably the most widely used parser in the world, and a really inanely simple repro. I wonder whether stuff like that would slip through as often were the parsing rules at all sane. And of course encapsulation of a document-fragment is tricky due to the context-sensitivity of the parsing rules; many valid DOM trees don't have an HTML serialization.
You can see that in the case where ASN.1 data need to be exchanged. You could decide to always send them in the DER form (conservative) but accept BER (liberal). BER is still an unambiguous encoding for ASN.1 data but allow several representations for the same data.
The problem with BER mainly lies with cryptographic signature as the signature will only match a specific encoding so that's why DER is used in certificates. But you can still apply Postel's law, you may still accept BER fields when parsing file. If the field has been incorrectly encoded in a varied form which is incompatible with the signature, you will just reject it as you would reject it because it is not standard with DER. But still, you lessen the burden to make sure all parts follow exactly the standards the same way and things tend to work more reliably across server/clients combinations.
If you only ever need the stored data on the client, localStorage is your pick. If you need to pass it back to the server with each request, cookies.
It would never occur to me to put something more than a simple token in a cookie. A username, and email address, some opaque thing.
The idea of trying to use it for arbitrary strings just seems weird to my intuition, but I don’t really know why. Maybe just because when I was learning about them long ago I don’t remember seeing that in any of the examples.
Csrf is no problem as the data from service worker is only active on the site itself. If you speak about csrf with a website where you can't trust js, you're site is broken as xhr/fetch use the same httponly cookies and is affected as well.
I think the distrust of js is a personal issue.
(Seriously though, someone trying to implement breadcrumbs fe-only)
I'm not a fan for jwt and it used more often than it should, but sometimes it makes sense.
Cookies are a bit of a mess, but if you're going to use them, you can follow the standard and all will be well. Not so much a minefield, but a hammer; you just need to take some care not to hit yourself on the thumb.
I guess the confusion here is that the browser is taking on the role of the server in setting the cookie value. In doing so it should follow the same rules any server should in setting a cookie value, which don't generally allow for raw JSON (no double-quote! no comma!).
Either use a decent higher-level API for something like this (which will take care of any necessary encoding/escaping), or learn exactly what low-level encoding/escaping is needed. Pretty much the same thing you face in nearly anything to do with information communication.
With a minefield, you can be doing something perfectly reasonable, with eyes open and even paying attention yet nevertheless it can blow up on you.
Here, though, there’s no special peril. If you just follow the standard everything will be fine.
If this is a minefield, then practically everything in software development is equally a minefield and the metaphor loses its power.
(Later in the article they touch on something that is a minefield — updating dependencies. There’s probably a good article about that to be written.)
The web in a nutshell.
- Implement redirects from the old login screen to the new one - Keep sessions in sync - Make sure all internal and external users know how to clear cookies - Remind everyone to update bookmarks on all devices - Troubleshoot edge cases
Can't seem to find the exact issue from googling it.
If the intent is to secure something then failing-open will indeed be at odds with that goal. I suspect you’re not implying otherwise, but rather expressing frustration that such providers simply can’t be bothered to put in the work and use security as an excuse.
Are we sure the website wasn't just broken normally? I kid, a bit, but good lord does Apple _suck_ at websites. Apple Developer and, more often, App Store Connect is broken for no good reason with zero or a confusing error message.
Note: I'm typing this on a M3 Max MBP (via a Magic Keyboard and Magic Mouse) with an iPhone 16 Pro and iPad Mini (N-1 version) on the desk next to me with an Apple Watch Series 10 on my wrist and AirPods Pro in my pocket. I'm a huge Apple fanboy, but their websites are hot garbage.
https://en.wikipedia.org/wiki/WebObjects
I can still remember when they'd purposefully take down their store page for some godforsaken reason. The mind reels
I know! You gotta let them cool down first. Learned this the hard way.
Web pages fail for me (javascript or whatever) far more often then I get a "violation access error" from my desktop programs.
The way around this, as a developer, is URL-safe-base64 encode the value. Then you have a bytes primitive & you can use whatever inner representation your heart desires. But the article does also note that you're not 100% in control, either. (Nor should you be, it is a user agent, after all.)
I do wish more UAs opted for "obey the standard" over "bytes and an prayer on the wire". Those 400 responses in the screenshots … they're a conforming response. This would have been better if headers had been either UTF-8 from the start (but there are causality problems with that) or ASCII and then permitted to be UTF-8 later (but that could still cause issues since you're making values that were illegal, legal).
And make sure to specify what exactly you mean by that. base64url-encoding is incompatible with base64+urlencoding in ~3% of cases, which is easily missed during development, but will surely happen in production.
It's called "urlsafe base64", or some variant, in the languages I work in.
> This encoding may be referred to as "base64url".
https://datatracker.ietf.org/doc/html/rfc4648#section-5
But yeah, it's not base64 followed by a urlencode. It's "just" base64-with-a-different-alphabet.
Try going to https://example.com/somepath and entering the following into the browser console:
document.cookie = "foo=a";
document.cookie = "foo=b; domain=.example.com";
document.cookie = "foo=c; path=/somepath";
document.cookie
I get 'foo=c; foo=a; foo=b'
Not to mention that the way to delete a cookie is sending a replacement cookie that expires in the past. How are you supposed to delete the right cookie here?
If you're ever in a situation where you need to invalidate all possible instances of a cookie, it's easier to just use a different name.
It requires a ping to a shared data source on every request. And, the same one for all of them. No sharding, No split domains... That gets expensive fast!
> In computer programming, a code smell is any characteristic in the source code of a program that possibly indicates a deeper problem. Determining what is and is not a code smell is subjective, and varies by language, developer, and development methodology.
For example, you set the currency to EUR in /product/123, but when you navigate to /cart and refresh, it's back to USD. You change it again to EUR, only to realize in /cart/checkout that the USD pricing is actually better. So you try to set it back to USD, but now the cookie at /cart conflicts with the one at /cart/checkout because each page has its own cookie.
I've never found a use for path-based cookies personally, but I'm not sure this is a particularly compelling example.
If not for this default behavior, it would have been much easier to manage global settings such as currency. Right now, all it takes is one cookie without a path to introduce inconsistency, only on some pages, in a way that's hard to reproduce.
The client won't get to decide which cookie to send where.
Looks like a good pattern to me.
What a colossal mistake.
Buy a second domain, ideally using the same TLD as your production domain (some firewalls and filters will be prejudiced against specific TLDs). Mimic the subdomains exactly as they are in production for staging/dev.
And if your marketing/SEO/business people are ok with having something like "prod" as a subdomain for all your production web pages.
We then have app-stg and app-canary subdomains for our test envs which can only be accessed by us (enforced via zero trust). No reason for marketing or SEO teams to care in any case.
I didn't really think about cookies back then but it just felt like a generally bad idea because disastrously messing up a URL in some config or related service would be much easier.
Stage, it depends - if you want stage to have production data with newer code, and are fine with the session / cookies being shared - host it on the same domain and switch whether users get stage or prod based on IP, who is logged in, and/or a cookie. That way your code doesn't have to do anything different for stage vs prod every time it looks at the request domain (or wants to set cookies).
If you want an isolated stage environment, why not just use a separate top level domain? Otherwise you are likely seeing yourself up for the two interfering with each other via cookies on the TLD.
If you are on /somepath I'd expect to get C as is the most specific value out of all three. All the values are still returned, ordered, which to me is the best of both worlds (path-specific values + knowing the globals)
The only thing I don't like is the magic `document.cookie` setter, but alas that's nearly 30 years old.
... this came up recently after I tightened the validation in jshttp/cookie https://github.com/jshttp/cookie/pull/167 - since that PR the validation has been loosened again a bit, similar to the browser code mentioned in the article.
My changes were prompted by finding a bug in our code (not jshttp) where a cookie header was constructed by mashing the strings together without encoding; every so often a value would have a space and break requests. I was going to suggest using jshttp/cookie's serialize() to devs to avoid this but then realized that that didn't validate well enough to catch the bug we'd seen. I proposed a fix, and someone else then spotted that the validation was loose enough you could slip js into the _name_ field of the cookie which would be interpreted elsewhere as the _value_, providing an unusal vector for code injection.
It is considered invalid syntax to lead with a dot by the rules. But it also must be ignored if present. Its lacking a “MUST NOT” because the spec is defining valid syntax, while also defining behavior for back compat.
It would break too many things to throw here or serialize while ignoring the leading dot. Leading dots are discouraged, but shouldnt break anyone following the spec. Maybe a warn log in dev mode if serializing a domain with dot, to try and educate users. Dunno its worth it though.
The point of jshttp IMO is to smooth over these kinds of nuances from spec updates. So devs can get output which is valid in as many browsers as possible without sacrificing functionality or time studying the tomes.
If you want to set invalid cookie headers, it's very easy to do so, I just don't think you should expect a method that says it will validate the values to do that.
The dot I can go along with because the behaviour is defined, but I'm less comfortable that a bunch of other characters got re-added a couple of days ago. As for smoothing over nuances from spec updates...the RFC has been out there for 13 years, and jshttp/cookie has only been around for 12; there have been no updates to smooth, it has just never validated to the spec.
I don;t understand why it's a problem that the client (in principle) can handle values that the server will never send. Just don't send them, and you don;t have to worry about perplexing riddles like "but what would happen if I did?"
They are the only place to store opaque tokens, so you gotta use them for auth.
See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#bl...
As a bonus we could get Persona-style passwordless future.
And I am not suggesting using local storage for it. I am suggesting adding browser support for standard/generic login UI. Basically think basic auth, just not so basic.
It's like technobros trying to invent an inferior train with each pod iteration.
And by what miracle browser would send Authorization header? Who sets it? For which domain it could be set?
Your comments remind me of the people who didn’t get HTTP verbs and wanted to use POST for everything before rediscovering REST.
A paradise for CSRF.
> Your comments remind me of the people who didn’t get HTTP verbs and wanted to use POST for everything before rediscovering REST.
REST is not about HTTP methods if you read the paper. It's curious you have a direct map between HTTP methods and REST verbs as your mental model.
The url can store state just fine...
I read the collected stories with my two year old, though I made sure we skipped the scary ones with the Dark Frog. I think the cookies ending was a little over his head, but we had fun taking turns acting out Toad pulling his blankets over his head when Frog tells him it's spring.
One issue we had was the reverse proxy inserting headers about the origin of the request to the server behind. Like ip, ip city lookup etc. And that parsed through a service written in go that just crashed whenever the city had a Norwegians letter in it, took ages to understand why some of our (luckily only internal) services didn't work for coworkers working from Røros for instance. And that was again not the fault of the Go software, but how the stdlib handled it.
Zoom or some other website our customers use was writing a cookie with quotes that would break the site. Amazingly hard to reproduce and debug.
Just dont make them, and dont accept them.
The "law" is: "Be liberal in what you accept, and conservative in what you send."
But here the problem is caused by being liberal in what is sent while being more conservative in what is accepted. It's using invalid characters in the cookie value, which not everything can handle.
Following Postel's law would have avoided the problem.
What?
Parse a cookie with http://php.adamharvey.name/manual/en/function.http-parse-coo...
Send a cookie with https://www.php.net/manual/en/function.setcookie.php or https://www.php.net/manual/en/function.setrawcookie.php
Or if you have to check how php populates the $_COOKIE superglobal I think it is somewhere is this file: https://github.com/php/php-src/blob/master/main/php_variable...
Most of the headaches around cookies seem to be around people trying to get them to work with arbitrary user input. Don't do that. Stick with fixed-length alphanumeric ASCII strings (the kind you use for auth tokens) and you'll be fine.