13 ms·
Do You Really Know CORS?
- officialchicken 8y agoI know it well enough that changing to a custom mime-type like "text/x-myapp-foo" is a solution that gets around CORS and pre-flight as well in the latest version of Chrome.
- mahesh_rm 8y agoCan you elaborate on this / link to a more detailed spec?
- Klathmon 8y agoAre you sure? That's a pretty insane security issue if it's true! Content-Type should only be allowed to be `application/x-www-form-urlencoded`, `multipart/form-data`, or `text/plain` to be allowed without preflight. Edit: I can't reproduce this on Chrome 69.0.3497.100 (Official Build) (64-bit). Setting the Content-Type to anything other than the above with a POST request will cause an OPTIONS preflight, even when using your example.
- officialchicken 8y agoI'm using 69.0.3497.81. Make sure your server accepts the header... after changing I stopped seeing OPTIONS requests in my server logs, not that it measurably improved the speed of the SPA. It was several months ago I made the change and FF behavior is definitely different (more relaxed?) than Chrome when it comes to CORS.
- TeMPOraL 8y agoThere's caching for successful preflights; maybe it's involved here?
- breatheoften 8y agoI know that chrome limits the amount of time that the CORS preflight validation response result can be cached (to a maximum of 5 minutes — and if the server sets expiration header to a longer time - chrome still only caches up to 5 minutes). Does Firefox perhaps not limit this? It could be that you are seeing a difference in behavior due to the max time that each browser is willing to cache the CORS preflight check ...?
- lysium 8y agoThis is really an informative article. We've recently stumbled across this issues and all other pages I could google did not explain it as clearly as this page.
- ottomanage 8y agoMy experience was the same as yours, resources explaining things assumed technical knowledge far beyond my level or were not very clear. This was a very well put-together article. My only contribution to the discussion is that if you get a CORS error where you wouldn't expect it, the problem might not be a CORS issue. I spent the better part of a weekend trying to debug why a request to a Google API wasn't working and why I was seeing a CORS error (same thing worked fine on another system). Turns out, it wasn't the same thing, my url had a typo...
- jchook 8y agoYou may also enjoy https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5 https://hackernoon.com/im-harvesting-credit-card-numbers-and...
- 3pt14159 8y agoI'm ideologically against third party on the web because it is a privacy nightmare. But I'm in the system that I'm in, and I don't take on fights that aren't possible to win, so barring my becoming a billionaire I've kinda just accepted that third party is here for at least a little while and I'm not going to refuse to use ads and analytics. Except on my personal website, that gets to stay cool. That said, CORS is the only thing about third party that I actually like. It's secure by default. That the ensure header and accept header are different things is amazing. I know all about the performance issues[0], but I'm ok with it in the right context. [0] It's kinda funny how against the herd I am here. I think it is shitty that the preflight sometimes doesn't happen. It's so weird to me that we carved out exceptions for this and seems like an otherwise secure-by-default system should have come with the guaranteed preflight.
- paulddraper 8y agoCORS is not necessarily about third parties. It's common to have app.example.org point to a CDN and api.example.org point to an API. And CORS implementation is terrible. The server has to transmit validation rules for the browser to enforce (with vendor specific caching differences), rather than just enforcing access itself. The reason it's implemented this way is because of the organic evolution of web security.
- ravenstine 8y ago> rather than just enforcing access itself. Could you elaborate on that? I can't picture the alternative you're suggesting.
- icebraining 8y agoSame here... from what I can tell, only the browser has reliable information about what's happening. How could the server know code from another domain is making the requests? And if anything, the web is more secure - desktop native applications can usually access each other's data and do malicious requests to remote servers using stolen credentials just fine.
- Klathmon 8y agoThis is an awesome overview! But don't take it as all encompassing, it doesn't go into some of the more esoteric edge cases with CORS, like: * either an unreleased safari version, or the most recent version will send preflight requests even if the request meets the spec (like if the Accept-Language is set to something they don't like). * If you use the ReadableStream API with fetch in the browser, a preflight will be sent. * If there are any events attached on the XMLHttpRequestUpload.upload listener, it will cause a preflight * cross-domain @font-face urls, images drawn to a canvas using the drawImage stuff, and some webGL things will also obey CORS * the crossorigin attribute will be required for cross-origin linked images or css, or the response will be opaque and js won't have access to anything about it. * if you mess up CORS stuff, you get opaque responses, and opaque responses are "viral", so they can cause entire canvas elements to become "blacklisted" and extremely restricted. I feel like I've cut my teeth on this API more than most, and I still feel like I'm only scratching the surface!
- saganus 8y agoGenuine question: why do you feel you've cut your teeth more than most? I.e. what kind of dev work do you do that makes you have to deal with this more than the average developer?
- meddlepal 8y agoNot OP, but my guess... Most devs aren't frontend devs and I would categorize this as mostly a frontend developer problem.
- harshvladha 8y agoI think: * Most devs are at least full stack * Most apps now-a-days interact directly/indirectly with browser * Attributing this problem to frontend devs without understanding why CORS and issues in handling that, makes you unaware of security issues with your backend services. FYI: I am a backend developer.
- nazri1 8y ago
- lwansbrough 8y agoI love CORS. I wouldn't be able to provide the level of security with my API that I do because of it. Without CORS, I don't believe my API design would be practically possible due to the security risks. If I have access to the Fetch API, I can tell the browser to send the user's cookie cross-origin and I can validate the request based on the origin. This allows for interesting authentication scenarios without the need for explicit client-user consent pages.
- acoard 8y ago>and I can validate the request based on the origin Are you talking about the HTTP referer? That's easily spoofable and can't be relied on server-side. The same-origin policy and all the CORS security is implemented in the browser itself, not in HTTP. If you need to be certain that a request originated from your own page and not another domain you need to use a CSRF token.
- lwansbrough 8y agoI'm talking about the Origin header, which is present on XHR requests and cannot be assigned by code. A CSRF token is not necessary if you require Origin because the origin is not sent with standard HTML forms.
- graphememes 8y agoIt can be inside of insecure browsers, you're not any more secure than you were before after CORS.
- lwansbrough 8y agoUsers with insecure browsers are subjecting themselves to security vulnerabilities, not me. In this case, the service just wouldn’t work for them. Not overly worried about those users because they represent a diminishingly small portion of our user base.
- 8y ago
- stesch 8y agoHad to deal with a firewall that filtered all unknown/"new" HTTP headers. This included CORS. A PITA to find the reason why Firefox wouldn't use the Google fonts.
- crooked-v 8y agoThat kind of crapware is why I'm increasingly glad that the http specs are moving towards being completely illegible to middleware boxes.
- edoceo 8y agoHow would http be any harder for middleware than app-layer? If both linked to libhttp.c, couldn't they each get the full parsing/reading/writing - wether proxy or server?
- crooked-v 8y agoBeing able to parse HTTP doesn't get anywhere when you can't actually get at the contents because they're encrypted (as with all major HTTP2 implementations).
- stesch 8y agohttps://www.howtoforge.com/filtering-https-traffic-with-squid https://www.howtoforge.com/filtering-https-traffic-with-squi... http://www.watchguard.com/help/docs/wsm/xtm_11/en-us/content/en-us/certificates/cert_https_proxy_resign_c.html http://www.watchguard.com/help/docs/wsm/xtm_11/en-us/content...
- parhamn 8y agoIm curious how many newer JS+API applications still use browser cookies as a means of authenticating API requests and how prevalent cookie usage still is for these types of applications? JWT/tokens + Local/session storage + adding fetch headers seems like the best way as long as you don't run untrusted JS.
- philcockfield 8y agoLocalStorage is so much more preferable than cookies, I agree, however as SSR ("server-side-rendering") of heavy client-side JS apps becomes more prevalent, suddenly cookies are back in business. If the initial SSR needs some initial client-state to complete its work before sending the HTML payload, it can see the cookie, but not localStorage.
- anthuswilliams 8y ago"as long as you don't run untrusted JS" is a surprisingly tough hurdle to hit, even for very experienced developers. What is your reason for preferring JWT + localStorage for authentication and session handling? I'm genuinely curious, as httpOnly cookies strike me as better in every meaningful way.
- emmelaich 8y ago> performantcode.com took too long to respond. ERR_CONNECTION_TIMED_OUT Too ironic not to mention.
- jedberg 8y agoMy only experience with CORS has been when trying to access api.foo.com from a web page on foo.com, and then getting denied. Then I messed with the settings on api.foo.com trying to get it to allow access from foo.com, and then I gave up and just configured the load balancer on foo.com to proxy requests to foo.com/api to api.foo.com. So far it's only gotten in my way as a developer. But it's there to protect users, not me. So at the end of the day, I'm glad it's there as a way to somewhat prevent people from tricking my users into hitting my api with malicious requests.
- dasil003 8y agoYou have it backwards. This type of request was not possible at all before CORS, CORS is what allows you to make it possible.
- stockkid 8y agovery nice article. I thought I understood CORS but learned some new things: * not all cross origin requests need to be preflighted * to use credentials, server needs to explicitly allow credentials to be sent from client
- JepZ 8y agoI never really understood why we have CORS. I mean, the problem with CSRF is that some random page can trick your browser into adding its authentication token to a request which does not originate from the authenticated page. So why the do we need the server to tell the browser that it should not send requests from other origins? In my opinion, it would have been much better to improve the browsers to not include cookies in 3rd party requests automatically (only when they are explicitly specified via JS for example). It should have solved the issue equally well, without introducing some bulky server-side security feature to remote control browsers.
- zackmorris 8y agoYa I generally think CORS is a waste of time. It would have been better to provide a hash of the file we're linking to and trust that rather than where it came from. Which is precisely what Subresource Integrity (SRI) does: https://en.wikipedia.org/wiki/Subresource_Integrity https://en.wikipedia.org/wiki/Subresource_Integrity Sadly even though this is an obvious concept and trivial to implement, it took them over 20 years since the web came out to get it in most browsers. The cost to society of having thousands of copies of the same commonly used files (like jQuery) hosted locally on countless servers rather than having a centrally hosted version already cached from previously visited sites is staggering to contemplate. I'd really like to know who was behind the holdup on deploying SRI.
- iancarroll 8y agoCORS is about a lot more than just static assets. SRI does not replace CORS.
- Ajedi32 8y agoCORS is for data retrieval, not subresource inclusion. In fact, you don't need CORS at all to include a script in your page; that has never been the case.
- visarga 8y agoIf they hashed and cashed the resource files, then they could be found locally most of the time.
- valtism 8y agoMirror: https://web.archive.org/web/20181004000006/http://performantcode.com/web/do-you-really-know-cors https://web.archive.org/web/20181004000006/http://performant...
- zero_kool 8y agoYou the MPV!
- guscost 8y agoCORS is a technical subsidy granted to (sloppy) users of cookie authentication. I’ve never worked on a project where it was anything other than an annoying hoop to jump through.
- alexnewman 8y agoI'd also argue it encourages worst practices
- matt4077 8y agoWhen has "subsidy" become the go-to narrative to argue against any sort of deference to real-world usage? You could just as easily frame CORS as "antibiotics for the people who dared to leave their house". (There's also a no-true-scotsman fallacy going on in your argument)
- guscost 8y agoMore like "mandatory medical testing at the airport because some people don't vaccinate" from my perspective. It's a "subsidy" because we all have to spend time on it, even though lots of people don't receive any benefit from it. It's not intolerable, the Web is based on community standards and responds to community needs, and I'm fine with that. But I'm always on the losing end of this one so I'm going to say so.
- jaequery 8y agoI tend to use jsonp to get out the cors restriction time to time
- wingi 8y agoBut jsonp have to be supported by your extern API.
- uyuyhay 8y agoPlease explain why browsers can't request and use any url as a regular curl command does (I'm explicit talking about request without sending browser cookies)
- jhabdas 8y agoI don't know CORS that well, but like any dev worth their weight in salt I know how to get around it: - iframe - domain js hack - reverse proxy - http header What else? Referrer Policies await.
- jpangs88 8y agoI agree, the only thing I have ever found with CORS is that it makes it difficult for people who don't consider it when planning out servers should run. It goes like this: - Just use my API... - I tried, please enable CORS. - What's CORS? I find it frustrating that this seems to be the default for most servers. I think it should be opt in and not opt out.
- dasil003 8y agoIn order to make it opt-in you’d need to disable cookies by default (at least for auth) or else you get massive pwnage by default.
- exabrial 8y agoNo... I don't despite my best efforts to be diligent about learning it. :( It's a workaround for a bunch of compromises we made where the cure is almost not worth the pain.
- stillbourne 8y agoI am very upset that no one said "Of CORS I do!"
- denormalfloat 8y agoWhy not just include the Origin on all cross-origin requests? Then the server could deny/allow it without the need for preflight.
- jraph 8y agoI would be concerned about the privacy implication of it. Imagine if the browser sent the origin to widely used CDNs, or to Google Fonts, and that people didn't actually block Google domains on their browsers. Also, this would not be secure by default, because you would have to change the default behavior of the server to block cross origin requests.
- kijin 8y agoBrowsers already send the referer header on all those CDN requests, provided that the CDN is loaded over https. If anything, the origin contains less information.
- otabdeveloper2 8y ago> Do You Really Know CORS? Of course I don't, nobody does.
- legohead 8y agoYou think you know CORS, and then your users visit your site with the Edge browser...
- bluepnume 8y agoI built out https://github.com/krakenjs/fetch-robot https://github.com/krakenjs/fetch-robot to avoid some of the esoteric issues around CORS endpoints -- and to avoid the performance hit of that preflight request. It acts as a `fetch` implementation that allows you to declare cross-origin policies in advance, then channel the requests through an iframe which enforces those policies.
- vks2108 8y agothe link is not working for me. Is there an alternative link.
- toonitw 8y agohttps://dzone.com/articles/do-you-really-know-cors https://dzone.com/articles/do-you-really-know-cors
- Thu27Sep 8y agoOne idea that the article doesn't convey well, in my opinion, is that the Same-Origin Policy only prevents the browser from reading the response from an HTTP server to third-party host, but it doesn't prevent the request from being issued in a first place. The CORS headers are merely a way for the server to indicate to the browser whether it is allowed to read the response of not, but it doesn't protect the server from anything. Especially, setting the "Access-Control-Allow-Credentials" header to true means that a client which sent a request with a cookie is allowed to read the result, but whether the request is sent with a cookie or not, and will be treated as such by the server, is entirely up to the client. So although malicious.com cannot read the details of bank.com using AJAX, it can definitely send a POST request to trigger the transfer from the user's account to a malicious account using the user's cookie (blindly so). This is the reason proper CSRF protection must be implemented by the server, independently of whether CORS is enabled or not.
- sbergot 8y agoThis is not entirely true. The preflight's role is exactly to prevent a post request to be sent to the server. There is no preflight only in particular cases.
- Thu27Sep 8y agoThis is entirely false. POST requests with headers set automatically by the user agent aren't preflight-ed. There is a preflight only in particular cases.
- dvdcxn 8y agoHow do you prevent people proxying your API via a node service? This is something I could never get my head around with CORS - what's the point of whitelisting origins if getting around the whitelist is nothing more than an inconvenience?
- Liquidor 8y agoCORS is mostly used to prevent attacks from a browser script on a non-whitelisted website (CSRF etc.). To prevent someone abusing your API otherwise, use an authentication method.
- chii 8y agoIt's not free to run a proxy like that.
- sciurus 8y agoThe user is still protected in that case. If you create a proxy for foo.com, your javascript can't get the browser to send the user's cookies for foo.com to your proxy.
- waffle_ss 8y agoI recently implemented a feature that depends on CORS and I don't see anything in this article that adds any value over Mozilla's thorough CORS docs.[1] If you're writing an article on CORS today I also think you should mention recent CORS developments such as Cross-Origin Read Blocking (CORB)[2] and features on the horizon such as Cross-Origin-Resource-Policy, Cross-Origin-Window-Policy, etc. that in light of Spectre, Meltdown etc. are meant to help plug speculative execution holes.[3] [1]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS [2]: https://www.chromium.org/Home/chromium-security/corb-for-developers https://www.chromium.org/Home/chromium-security/corb-for-dev... [3]: https://www.arturjanc.com/cross-origin-infoleaks.pdf https://www.arturjanc.com/cross-origin-infoleaks.pdf
- afs35mm 8y agoHere's one question that's always bugged me - What's stopping a malicious user from sending an HTTP request from any API client like Postman, or even Curl from the CL? Something like a post with: {transferTo: myAccountId, amount: 1000000000}? Obviously in any nontrivial web app it would fail because of authentication issues, but if a server doesn't do ANY sort of security checking, that should work, no? Does that mean that the onus is on the server developer of mybank.com? And if so, what would stop the malicious request from working on any server developed before the existence of CORS?
- joevandyk 8y agoServer is supposed to check authentication/authorization through some method. If HTTP, that’s done via setting some information in the request headers, be it a cookie, or basic auth, or token auth, or similar. CORS is done by the browser - to not allow certain requests to be made (In case you are accidentally executing malicious javascript code). The server tells the browser via the CORS headers which requests are ok to make.