logoalt Hacker News

Developers don't understand CORS (2019)

299 pointsby toilettoday at 1:35 AM238 commentsview on HN

Comments

muvlontoday at 6:05 AM

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.

show 9 replies
supriyo-biswastoday at 5:40 AM

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...

show 1 reply
kittywantsbacontoday at 7:35 AM

I think this is legitimately the least informed HN comment section I've ever seen. Entirely proving the author's point.

show 3 replies
encomiasttoday at 3:17 AM

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.

show 5 replies
default-kramertoday at 4:06 PM

I understand how the Same Origin Policy protects browsers from executing malicious scripts. I also understand how the Access-Control-Allow-Origin header can be used by servers to declare additional origins as trustworthy, relaxing the SOP.

What I still don't understand is what purpose the Access-Control-Allow-Headers header serves. It doesn't seem like it improves security for the browser (and definitely not for the server). Was it included "just for completeness" by the protocol designers? See also https://stackoverflow.com/questions/17992042

simonwtoday at 12:33 PM

To understand CORS, you have to understand the Same Origin Policy.

If you find CORS difficult to understand, particularly the question of "why do we need this?", I suggest starting here: https://developer.mozilla.org/en-US/docs/Web/Security/Defens...

I've tried using the Same Origin Policy as an interview question in the past, but it's not a good question because the majority of candidates aren't familiar with it, so you learn very little by bringing it up.

show 1 reply
himata4113today at 8:02 AM

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.

show 2 replies
mparnisaritoday at 6:11 AM

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.

show 3 replies
dangtoday at 5:52 PM

Discussed at the time:

Developers don't understand CORS - https://news.ycombinator.com/item?id=20404578 - July 2019 (355 comments)

piyhtoday at 2:40 AM

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.

show 1 reply
StrauXXtoday at 8:42 AM

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).

revetkntoday at 2:56 PM

I did not really understand CORS until I sat down and wrote a server implementation of it and had to think hard about "what hooks should be exposed to developers for controlling it?"

Most of us I think just "expose a set of whitelisted origins and be done with it".

Here is where I landed for how to specify your server's CORS policy:

https://soklet.com/docs/cors#custom-workflow

jdw64today at 3:02 AM

Sometimes I'm not even sure what I truly 'understand.' When even senior engineers working on products used by hundreds of millions of people, like Zoom, have had these kinds of issues, it makes me wonder. So I usually just write code the way it was left by my seniors, out of inertia. But I realize that the area I work in is actually incredibly abstracted.

ozimtoday at 5:56 AM

Issue is that for most projects CORS is set and forget. You don’t run into it once a month or even once a year - you run into it when setting up new project from scratch.

Many or most developers work on existing projects that have all kinds of security defaults set somewhere in the past and no one bothers reviewing those.

show 1 reply
kartoshechkatoday at 5:36 AM

- cors docs are written either from solution or implementation point of view, not the "why this exists, and how we successively deal with bad actors trying to game cors", cors RFC is terse

- protocol itself is quite nuanced, like iirc requests with Authorization (or some other) headers don't obide by usual rules, and again for developer it's just an arbitrary convoluted set of rules, if they don't grasp the problematics

- backend and frontend should work in unison to have correctly configured cors, but as we know, devs hate communicating with each other

xg15today at 10:47 AM

CORS seems to be the Offside rule of the webdev world.

I wonder if much of that misunderstanding comes from the threat model being quite unusual and not always easy to understand.

For starters, there are three parties, which all don't trust each other: The server, the browser and the JavaScript running inside the browser.

The browser is supposed to protect the server against requests from unauthorized JavaScript applications. CORS is there to mark certain requests as "authorized", while keeping the protection active for the rest.

But the entire system only works if those three components exist in the first place, as enforcement is solely relying on the browser.

frogulistoday at 3:23 AM

From my experience, the reason CORS is hard to understand is that it's somehow inverted from the default "shape" of security in web dev.

We easily form the intuition of the client being a by-default untrusted entity, and checking whether it has the privilege of accessing this data, where the server is the arbiter of that access.

CORS is so inherently different to that, and while the information is easily available, it requires a short but careful read to grok the idea -- which a dev tunnel-visioning towards getting their application code written may not wish to slow down for.

show 1 reply
dofmtoday at 11:24 AM

Part of the issue is developers imagining a theoretical solution to a wider problem than CORS is trying to solve.

Once you understand that it's onlying to solve problems that happen in a user's compliant browser, and not some wider issue of resource authorisation, it does get a bit easier to understand.

Though in a way CORS seems too simple for what it achieves.

apitmantoday at 5:00 PM

> Is the CORS API too complex and confusing

Yes

physixtoday at 4:42 AM

> Developer's don't understand CORS

Count me in!

show 1 reply
rubendevtoday at 9:24 AM

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.

show 1 reply
Calgaryptoday at 3:40 PM

I remember as a student that CORS problems drove me crazy. 6 years later, nothing changed

preommrtoday at 3:55 AM

Because, like many things in web, it's a patchwork of compromises due to legacy issues, rampant inconcistencies and trying to be too clever.

You get results where it's really difficult intuitively understand it because at that point you're not really meant to. Realistically, people just follow a guide, or some lib, and move on.

xtractotoday at 4:26 PM

Ha! I kind of understand (apparently not really well from reading comments) CORS and many other web dev related constructs but oftentimes choose to work around them like what the zoom people did on the article exactly for this reason:

https://news.ycombinator.com/item?id=48616086

The whole thread shows that It seems even highly technical people that supposedly know a lot about this shit get it wrong. Because the mechanics are so complex, nobody really knows how they really work. Or it is a freaking mess or chore to achieve something.

Similar to just making a website HTTPS... even with let's encrypt and certbot , why does making a site https have to be so hard? (Try it on a service within a vpn).

sivalustoday at 3:36 PM

CORS could be handled by your SRE/DevOps/Security equivalents and they will probably do it better because they more often operate while seeing the entire landscape. Feature developers are typically trying to work in a particular area at a time and lose 'peripheral vision'. Or maybe it's something to be learned at the staff/late senior level where you can get more of that perspective because you should have more freedom. The situation in this article also means this was missed by their security folks as well.

Who decided this was a developer's responsibility?

yearesadpeopletoday at 1:25 PM

The comments - helpfully - are great examples of the essence of what the article is attempting to communicate. Bravo!

confidantlaketoday at 11:48 AM

I thought I knew CORS before but after reading all the comments I don't think I know anything anymore. Guess I will just make a coffee and move on with my day.

thomask1995today at 6:52 AM

I think some sort of gui to help write the cors headers would help tbh.

it's quite difficult to get your stack to work for local dev, CI, and prod since each most likely needs different cors headers. Especially if you use tunnels and proxies like we do.

What made it click for me though was understanding what problem it solved.

stephbooktoday at 4:35 AM

I still don't understand the threat model and, obviously, it's not explained here either.

I log in to social.net. I click on scam.org and change sites. I'm on scam.org and it triggers a request to social.net/friends.

No cookies are sent, no JWT. I'm not logged in and get a "Needs login" HTTP error. Nothing bad happens.

I thought that's how it works without CORS already.

show 4 replies
piterrrotoday at 4:45 AM

Wait, isnt it implemented because of the sheer number of broswers that could be used at the Zoom’s scale? They could’ve used jsonp too it they wanted to bypass CORS. Using image with different dimensions sounds like the most bulletproof way across multiple devices/OSes/browsers

rho138today at 9:30 AM

People hating on web developers and/or saying application developers are better and then everyone bombs the RFC challenge.

deathanatostoday at 2:50 AM

Generally when I'm debugging these, I need/want to know what was the preflight (if applicable), and was the preflight what was expected? When I help others debug these, generally I find there is little expectation of what the preflight "should" be, and instead just a bunch of stochastic attempts to adjust the server's response headers to get the browser to capitulate — regardless of whether that makes any sense at all.

I would also say I think Firefox's network inspector is better in this area. (But I'm often having to ask others to "no, don't send the failing request, send the CORS preflight", we need to understand what happened with it.)

> Anecdotally, lots of developers I’ve talked with don’t understand well how CORS works.

Yeah, most FE devs I've worked with seem to not understand CORS.

> Is the CORS API too complex and confusing

I think it can be hard if you don't understand why the exceptions to preflights are what they are, but the moment you internalize "because the browser can already emit that request in other cases" then it becomes obvious what categories are what & why.

Izmakitoday at 9:14 AM

I don't fully understand CORS and was hoping he'd explain how it works. :(

PunchyHamstertoday at 3:43 PM

CORS is just patch over patch over patch on a terrible idea on how to provide theatre of security

drchaimtoday at 8:37 AM

I understand CORS each time I need to fix or to avoid them ;)

ktzartoday at 12:02 PM

it's one of my favourite interviews questions and very few people get it right.

karoltoday at 9:33 AM

CORS, CSRF and CSP get the job done;)

thegingertoday at 9:52 AM

Cors is hard to understand because the browser is protecting you and the server from malicious code that the developers are not expecting to be there. Its a hypothetical threat you cannot see during development unless you really go out of your way. If you can't see the threat it's hard to understand it, it you don't understand the threat it's hard to understand the protection against it.

Its one of those situations where you need to think like an attacker to see the whole picture.

robertclaustoday at 3:38 AM

I bet there's an awful lot of servers out there that will happily take CORS requests from any host because someone didn't understand why their second domain couldn't talk to the same API.

show 2 replies
foundarttoday at 5:08 AM

Correct. Where are some good explanations?

ottofluxtoday at 5:00 AM

the amount of code i've seen either allowing * when it shouldn't because someone was desperately trying to make their code work is astounding.

contractors, "specialists", etc. who never took the time to read how CORS works and how simply you can handle a list of allowable sites, etc.

it's only complicated until you take the 5-10 minutes to properly understand what happens where. if you don't know, go do it now.

show 2 replies
threethirtytwotoday at 10:34 AM

AI understands CORs. So that's something AI does better than developers.

rusktoday at 7:48 AM

It’s TOS for using ebdpoint. It says:

access is provided under condition you respect these restrictions

You are not obliged to honour this. It is not enforceable so it seems strange.

Browsers enforce it, but it can be turned off and nobody expects it to be implemented by a simple REST client application.

It’s a gentleman’s agreement. It’s a statement of expectation to the browser. On the one hand it may be for the protection of the browser user, from cross site attacks, and from malicious code on the web.

But crucially it provides little protection for the endpoints themselves bar accidental misuse.

It is very unusual and rare example of “cooperative” security in a web that’s frequently so adversarial.

And that’s what makes it hard to grasp.

show 1 reply
d--btoday at 6:56 AM

A CORS protected endpoint tells YOUR BROWSER not to let YOU access its content if the website you’re browsing from is not whitelisted.

It’s confusing because unlike most security features, it’s meant to protect the users from themselves. The risk comes from a combination of users being allowed to visit malevolent sites and browsers letting all websites do a lot of random stuff, including making 3rd party requests with cookies and private stuff

show 3 replies
dborehamtoday at 3:36 AM

The only thing to understand is that it does nothing useful today.

show 2 replies
lofaszvanitttoday at 10:37 AM

Because they don't like reading docs. At the same time it is an overcomplicated fucking mess, just like CSP headers just like css syntax/wording. Somehow everything that is security related is overly complex.... it's a miracle!

ralusektoday at 7:47 AM

I understand CORS and I don't.

TL;DR: It's a restriction your browser gives itself. If it's on Domain A and it sees a request going out to Domain B, unless Domain B responds saying that it's expecting traffic from Domain A, the browser prevents itself from making the call.

I think the part about it that is off/silly to most people is that it's not a normal security threat model, because a malicious client could simply just...not impose that restriction on itself. You're perfectly capable of going and curling that same request to that backend, or calling it from an app, or any number of other things. So it's not really protecting your protected resource, the backend, from malicious clients.

All of that is where I feel like I understand clearly. The part I fail to retain is the exact scenarios it does protect against, which IIRC, are basically about attempting to protect your users from being misguided on other clients that are acting as your client, something like that (but again, this literally only applies to browsers). It's just kind of a weird niche problem that I often find myself thinking "I mean why is the user on another client and have allowed themselves to authenticate on that client with my server...this sounds like the user's fault."

show 2 replies
sala0986today at 2:06 PM

[flagged]

ankitraj1224today at 1:01 PM

[flagged]

formit34today at 8:06 AM

[dead]

🔗 View 12 more comments