Top
Best
New

Posted by toilet 8 hours ago

Developers don't understand CORS (2019)(fosterelli.co)
196 points | 102 comments
muvlon 3 hours ago|
Even TFA seemingly doesn't understand CORS. Or at least misreprents it grossly:

> The webserver listening in on localhost:19421 should implement a REST API and set a Access-Control-Allow-Origin header with the value https://zoom.us. This will ensure that only Javascript running on the zoom.us domain can talk to the localhost webserver.

No, that does not do that. JavaScript from any other website can still talk to localhost:19421 just the same. CORS doesn't restrict anything, it loosens the default set of restrictions (ignoring preflight requests for now and assuming we're talking just about "safe" Methods). That Access-Control-Allow-Origin header just allows JavaScript running on zoom.us to read the responses when it queries localhost:19421. The requests happen in any case, and you must ensure in your backend that they don't cause any adverse effects.

Lerc 2 hours ago||
I don't think you can even say CORS does that.

The degree to which CORS is poorly understood (I have read numerous (often contradictory) documentation and I don't really understand it.) means that you can't rely on it being implemented properly by an unknown party,

If a protocol reaches this level of widespread confusion, I think all bets are off. Even if one end of a system performs correctly, who's to say that the other will. If people adapt their code until it works with another implementation, were they mistaken, or the other end?

RobotToaster 1 hour ago||
It seems like nobody understands CORS.

Including me TBH.

bwblabs 1 hour ago|||
Another quote from the article:

> Further, native apps can generate a unique self-signed certificate.

Just creating a certificate will not work, unless it's installed as root CA certificates in all browser trust-stores on the machine. And if the private key of the root CA is not secured correctly, one could MitM any websites. So at least you want it name constrained (https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1....), but at least in Chrome until 2023 (v112) that did not work on root CA's (https://alexsci.com/blog/name-non-constraint/), so you had to add an intermediate CA and add the constrain there. Of course, you should also just throw away the key of the root CA.

I will admit I once added basic constrains in some project with a local root CA (2020-2022), but 'incorrectly' to the root CA, and did not test it in all browsers.

SahAssar 1 hour ago||
> assuming we're talking just about "safe" Methods

That's a pretty big assumption. Any decent webdev should not let GET/HEAD/OPTIONS modify state (joining a meeting is changing state) and additionally PUT/DELETE should also be idempotent.

POST with JSON (or other non-form formats) api's should also have it's content-type header checked (text/plain forms can send a JSON body but the content-type will be text/plain). PUT/PATCH/DELETE and POST with a non-form content-type (application/x-www-form-urlencoded, multipart/form-data, or text/plain) will trigger a preflight so that CORS is properly checked before the actual request reaches the server.

bwblabs 1 hour ago||
> Any decent webdev should not let GET/HEAD/OPTIONS modify state

> additionally PUT/DELETE should also be idempotent

Yes, but I think the majority of large web applications are not fully correct in terms of 'Safe and Idempotent Methods' (https://datatracker.ietf.org/doc/html/rfc9110#name-common-me...).

kittywantsbacon 2 hours ago||
I think this is legitimately the least informed HN comment section I've ever seen. Entirely proving the author's point.
ghoshbishakh 1 hour ago||
100% - although it is stunning to see since most LLMs get CORS questions right (which is surprising since they trained on all sorts of incorrect data).
Finbel 1 hour ago||
Maybe it’s like that trick where if a thousand people guess the amount of beans in a jar almost all of them will be wrong but their average will be very close to, if not, correct.
gib444 40 minutes ago||
Guidelines say to edit out swipes, so your comment can be edited to just:

""

encomiast 6 hours ago||
It's not just CORS that's hard to understand. Many (most?) developers don't really understand the threat model. And even when it's explained it hard to see why it's a big deal. Part of this is that backend developers usually have to configure CORS and it's not an access privilege protection. From the point of view of the backend it doesn't seem to matter. Bad guys can't get it. From the point of view of the front-end it's often seen as a nuisance.

The article does a nice job giving a concrete example.

mrweasel 2 hours ago||
We had a project were the same developer wrote the frontend and backend and still managed to get CORS wrong. As the operations people we rewrote them correctly in the load balancer... well I assume correctly, at least the application now works.

CORS is really hard to wrap your head around, but sadly there's also a ton of developers that not only fail understand the threat model that CORS guards against, they also don't understand webdevelopment in general, especially the http protocol. I find that somewhat strange, because they also can't do native application.

stephbook 1 hour ago||
> I assume correctly, at least the application now works.

That's like saying the lock works because people can enter the building. What about keeping the bad guys out, which is the whole point?

yaur 5 hours ago|||
It’s not that hard to understand… in the cors threat model an attacker gets one your users to take an action on your site by visiting their site.
hn_throwaway_99 4 hours ago|||
> in the cors threat model an attacker gets one your users to take an action on your site by visiting their site

This is really oversimplifying things, incorrectly IMO, and that sentence makes it sound like you're confusing a CSRF vulnerability with CORS protections. Normally when you write a backend server you implement some sort of authentication and access control, and in that scenario the threat model that lets "an attacker gets one your users to take an action on your site by visiting their site" is a CSRF vulnerability, unrelated to CORS.

The scenario presented in TFA is actually a very special case, because the bug is with a webserver running on localhost that doesn't (apparently) implement access control - not something most web apps entail.

In fact, one of the parts that confuses a lot of people is that CORS rules only prevent the JavaScript web client from reading the response from a remote endpoint - if the endpoint is available on the public Internet then anyone can still make a request to it.

The other thing that is confusing about CORS is that browsers already let you load lots of resources from cross origin servers - you can load images (as TFA points out that Zoom did as a workaround), scripts, stylesheets, form submissions, etc. The one thing you can't do, unless the server implements the appropriate CORS headers, is make a cross origin fetch request from JavaScript.

ctidd 4 hours ago|||
All CORS does is allow for selective loosening of anti-CSRF controls. CORS is a mechanism for a service to tell a client “I’m CSRF-resistant” so that that the client doesn’t need to protect its user as tightly when interacting with that service.
webstrand 3 hours ago||
Isn't CSRF about forging mutating requests? CORS doesn't block the underlying GET/POST request, the request still goes through and the server still needs to properly implement CSRF prevention. CORS just prevents javascript from reading the response.

CORS _additionally_ requires OPTIONS pre-flight to succeed, before allowing any kind of request outside of what can be achieved with a HTML form submit action. So it blocks PUT/PATCH/DELETE, specifying most Content-Type, and specifying nearly all other headers. But this is just blocking "non-standard complex requests that might confuse badly programmed pre-javascript-era servers".

It passes all standard requests that you could have made by: embedding the url as an image src, the target of a HTML form, endpoint for csp reports, etc. All still need to be checked methodically by the server for CSRF if it's going to take any mutating action due to the request.

mycall 1 hour ago|||
> CORS rules only prevent the JavaScript web client from reading the response from a remote endpoint

Assuming the web client plays nicely. I commonly bypass CORS for playwright unit/E2E testing.

harrall 5 hours ago|||
It’s easy to understand but most people don’t naturally think of ways people try to break in. Without thinking about that, the importance of security is low.

It isn’t a knowledge thing (though it could be), or a capability thing, or intelligence. It’s pure mindset.

Ask yourself: is the average person noticing holes in fences and trying random doorknobs… probably not.

But on the other hand, most security people don’t think of product or UX (but some might) so that’s why you have roles.

cookiengineer 5 hours ago|||
On top of that, it's a threat model that doesn't make really sense from an attacker vs defender perspective. Because it's optional, and all kinds of other libraries and tools can just blatantly ignore it anyways.

CORS literally exists only against XSS and CSRF for actively logged in human users. Anything else in CORS is absolutely pointless because every other attack scenario uses scripts or programs that fake HTTP headers anyways. It's just as useless as the Sec-CH (client hint) headers because some Browser made by a company that starts with Micro and ends with Slop decided that the User Agent always needs to be Windows 10 for compatibility reasons.

That is why you see everyone just enabling every CORS option anyways, even though that is literally the worst case that allows XSS and CSRF. And a lot of websites have user edited content at some place, at the very least in images that aren't filtered for embedded scripts (PNGs, anyone?).

wonnage 5 hours ago||
What else is there in CORS? It’s all basically a way for an origin to communicate to the browser which other origins it can share data with. Of course if there’s no browser involved then there’s no need for it.

Client hints are useful for all the shitty “responsive” websites that don’t know how to use media queries. And for ad tracking. Mostly the latter

vachina 3 hours ago||
CORS is amazing for when you want to prevent people from (easily) stealing your bandwidth and hosting resources. Thieves have to stand up their own proxies, which makes them very easily blocked.
trick-or-treat 2 hours ago|||
I think you're confused. The only thing blocked would be client side fetch. You need to find another way to protect everything else.
inigyou 1 hour ago|||
How's it going with AI scrapers for you
supriyo-biswas 4 hours ago||
I wish more people read the CORS article on MDN[1] which helped me a lot at the time when I was trying to understand it. I knew some people had trouble with CORS but had no idea it was this bad, going by the comments here.

[1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/COR...

himata4113 1 hour ago||
It was pretty amusing reading the comment section so I'll chime in: SOP protects you (the browser) from leaking information to websites that should not be able to access that information and CORS allows you to weaken it.

Example: SOP stops example.com from fetching the list of subscriptions on youtube.com. But CORS allows example.com to access youtube.com/public/*.

This is also not the sole use-case, it also stops your backend api being up under a different frontend which would allow data theft since you could log into real services on google.com, but you're actually on g00gle.com enabling data exfiltration because now every request can be MitM'd.

StrauXX 1 hour ago||
No, it's exactly the other way around. The SOP protects you from these security issues. CORS is a feature that can be used to loosen up the SOP, to allow more complex inter-application behaviour.
himata4113 1 hour ago||
ah right, my own brain got jumbled from reading all the comments forgetting that cors: '*' is not the default.
crackalamoo 1 hour ago||
I love this, easy intuitive explanation
piyh 7 hours ago||
The only thing I remember about CORS is that it takes way longer than expected to debug, by design the error messages sent to the browser are intentionally gutted, and CORS error scenarios are hard to tell from other failure modes atfirst glance.
deathanatos 7 hours ago|
> by design the error messages sent to the browser are intentionally gutted

A CORS error is not "an error message sent to the browser", it is an error generated by the browser, because the browser has decided it cannot permit the request. (Though certainly a server can not understand a CORS request as such, and returned a weird response, which would then end up getting translated to a CORS failure.)

ameliaquining 6 hours ago||
I think what the person you're replying to is trying to say is that the web-accessible error message (i.e., the one that JavaScript running in the sending page can read) is intentionally opaque and somewhat misleading, because a more helpful error message would leak information about the response that the sending origin isn't supposed to have. There's typically a more helpful error message in the dev tools (which JavaScript running in a page can't access), but you have to know where to find it.
moring 6 minutes ago||
The message in the dev tools is, at least for Chrome, extremely developer unfriendly: The blocked request is displayed in a very strange way, without any information that it was blocked, nor that CORS was the reason for it, nor how that decision was made based on the preflight request.

You have to already know from experience that these strange devoid-of-information requests have been blocked by CORS, then find the preflight request, and there you will find a bit more information, but still much less than would be possible to show.

Showing more information would, AFAIK, not circumvent the layer of security that CORS (or actually origin isolation, which CORS makes an exemption from) adds. My best guess is that this just had very low priority when building the dev tools.

StrauXX 1 hour ago||
This blog post is very misleading.

> So what would a secure implementation of this feature look like? The webserver listening in on localhost:19421 should implement a REST API and set a Access-Control-Allow-Origin header with the value https://zoom.us. This will ensure that only Javascript running on the zoom.us domain can talk to the localhost webserver.

First of all, its not CORS that protects. CORS is an anti-security feature. What does protect is the SOP (same origin policy). The SOP (or SOPs rather, it's not really one feature but more of a paradigm in the standards) blocks documents from one origin, from reading data that belongs to another origin. This is the reason why `let w = window.open("https://example.com"); console.dir(w.document.body);` will work when it is ran from example.com, but not wikipedia.org. Only when protocol, host and port match, can documents access each others data (there is an interesting differential with cookies here, their SOP only looks at protocol and host, not port).

Importantly, the SOP only blocks reading data from other origins, not writing! So while example.com won't be able to read the response of a post request it sends to wikipedia.org, the request is sent and processed nontheless!

CORS now is a feature that allows sites to loosen up the SOP. This allows documents to read cross origin data nontheless. Namely, HTTP responses. (Standards for reading other kinds of data cross origin exist, but are not related to CORS).

mparnisari 3 hours ago||
I'm one of them. CORS is THE topic that I have to get a refresher for periodically. It's like I forget about it, it never sticks. I'm a backend developer so I never encounter any cors issues. Maybe that's why? I seem to forget things that I don't use on a day to day basis, so.
cyberrock 2 hours ago||
The DX for CORS and CSP is horrible because none of the browsers point out where the problem is coming from. In a sane world they would all write "response header" or "meta tag" somewhere in the message but the Riddler, Jigsaw, the Cheshire Cat were each hired by the major browser vendors to write the error messages. Chrome is the closest with "requested resource" but that's still downright cryptic. But on the other hand I'm glad all three of them still agree on something.

Edit: I realize that this is a fairly non-constructive comment, so to fix that, my suggested replacements are:

    Resource https://bank.com doesn't allow cross-origin requests due to lack of CORS headers. (Link to preflight request in Network tab) CORS protects against unaffiliated sites requesting data from your server. (Link to MDN)

    Resource https://bank.com doesn't allow cross-origin requests because this origin isn't in its CORS allowlist. (Link to preflight request in Network tab) ...

    Resource https://... can't be fetched due to CSP headers in this page. (Link to page request headers or meta tags in inspector) CSP prevents unauthorized scripts from executing on your page. (Link to MDN)
yen223 3 hours ago||
The biggest problem with CORS is precisely that most CORS errors show up as a frontend problem - specifically, a browser problem - but it needs to be fixed on the backend
rubendev 27 minutes ago||
This is really a self inflicted problem. If you host your backend on the same origin as your frontend (using a reverse proxy) you don’t need CORS at all and you can use the vanilla SOP, and strengthen it further with a strict CSP.
rho138 21 minutes ago|
People hating on web developers and/or saying application developers are better and then everyone bombs the RFC challenge.
More comments...