Modern browsers block cross-origin-requests.

That means, this will be blocked:


Why blocking those requests?

  • it's bad when content is loaded the user hasn't explicitly requested (e.g. ads)

But now, there is CORS. This means, the server decides, wether the request is going to be blocked.


  • APIs
  • knowledge databases


  • well, ads want to be seen as well. This means, malicious content isn't stopped if the content wants to be seen.

This means, it is easy to workaround the block – using a proxy that doesn't block itself and says it wants to share its content (Allow-cross-origin-requests). (Example: cors.io) But this adds other risk – since another site has to be trusted and the whole origin page functionality doesn't work anymore, when one site stops answering.

So what kind of security comes from blocking cross-origin-requests?


2 Answers 2


OK, both the question and Geir's answer show some serious confusion, so I'll try to clear things up a bit...

Same-origin policy (SOP) is a browser security feature that limits interaction between websites. Broadly speaking, it prevents site A from viewing the content of site B. This is important, because otherwise if you were logged into a site like Facebook, any other site that wanted to could view and even take actions in your Facebook profile! This would also apply to things like online banking, shopping, or business management. It is necessary for the security of any web site that requires you to sign in or otherwise authenticate yourself.

Some of what SOP prevents is simple enough to understand, like with XHR (XMLHttpRequest) and Fetch, where it prevents the requesting site from seeing the content of the response. However, it does NOT prevent the request from being sent, in most cases (it does, by default, block some kinds of advanced cross-site requests, such as with custom headers). After all, there's no point preventing simple requests - GETs or POSTs with standard content types - because a malicious website A that wanted to attack B could simply create an HTML form that automatically submits itself to B with whatever data the attacker put in it, and all of the user's cookies for B would be included with the request. SOP also prevents most interaction between iframes and their parent pages.

However, there are some things that SOP does not prevent. For example, a web page can include scripts and images from external sites. Since web advertising is almost always done by loading images and scripts from external sites (and for that matter, web tracking works the same way), SOP does not prevent advertising in general. SOP also does not prevent CSRF, unless there's protection such as an anti-CSRF token being used, in which case SOP is important(otherwise the attacking site could just read the anti-CSRF token from the target site, and then submit it with the forged request).

Cross-Origin Resource Sharing (CORS) is a way for site B to tell a browser "hey, I want you to relax the same-origin policy with regard to site A, but only in these very specific ways". More specifically, the most basic thing CORS can do is allow standard XHR and Fetch requests (which are made using JS) to read the response content, which is normally not permitted. It can also allow more complicated things, like allowing site A to set specified custom HTTP request headers (which is normally not permitted) or content types outside of the ones that HTML elements can submit (which is also not normally permitted). For example, CORS might be used to allow two sites that trust each other (like security.stackexchange.com and stackoverflow.com) to share information using client-side requests. Or it might be used to provide a web service API that a site like Twitter can use to programmatically reveal the content of tweets to other sites, again client-side (i.e. without the browser needing to ask the current site's server to send that request for it).

However, to be clear, CORS doesn't "protect" anything at all. All CORS can do is poke holes in the protection of SOP. CORS was developed to provide a safer way around SOP than the things some sites were doing instead, like JSONP (which was a clever hack but a security mess). CORS lets you relax SOP in only the ways you want to, for only the sites you want to.

Hopefully that also answers why both SOP and CORS are useful. In general, you shouldn't enable CORS on your server (that is, send CORS response headers) unless you need to, and if you do need to, you should enable it only for the stuff that needs it. I've seen some sites that use CORS so liberally that they've basically turned off SOP for their whole site, which would let any malicious site on the whole Internet view and control the misconfigured site for any user that was logged into it and visited a malicious site.


Using a proxy as an intermediary to inject CORS headers would not work, because your credentials (cookies) are subject to similar rules as the remote fetch() itself.

The same origin policy restricts the manner in which an attacker's site can call resources on another site you are logged in to. And CORS allows you (as the API provider) to relax those rules for websites you trust. The idea is that the browser, as your trusted agent, validates that the website is indeed authorized to do what it attempts to do.

Say that you are tricked into browsing to https://evil.org/, where an XHR calls the transfer-funds resource at your bank. The attacker's site attempts something like:

POST /transfer/ Content-Type: application/json Host: yourbank.com Cookie: ???? Origin: https://evil.org
{toAccount: "attackersaccount", amount: "1000USD"}

If you already are logged in to your bank, and the browser would allow the page to include your credentials (eg., session cookie), the transfer would be approved.

Or would be, without same-origin policy and CORS. To be sure that the the page is allowed to call resources on a remote API, it would check with the API (a CORS prefligh) using the OPTIONS method. As the API has never heard of the origin "evil.com", it refuses to complete the call.

If you tried to add a proxy as an intermediary here; where your "evil.org" proxy resource forwards the calls to the bank resource, any cookies on "yourbank.com" would simply be omitted due to not matching the proxy domain "evil.com".

Hope this explains why the CORS mechanism is put on the API side. As MDHacker points out, there are a lot of details here to be aware of. I've to tried to keep the answer matching the core of the question.

  • 1
    This is incorrect. CORS does not protect against CSRF. In fact, CORS doesn't protect against anything at all; CORS is a way to open holes in same-origin policy. However, your example - which uses a simple GET request - would still be hilariously vulnerable, and there's basically nothing you could do to block it (the one thing that comes to mind is cookies with samesite=strict and I'm not sure you couldn't get around that too).
    – CBHacking
    Commented Jun 23, 2018 at 1:48
  • This is just a simple example of what the Same Origin Policy protects against, and why it helps. Even my simple example is protected, as cookies would not be passed to the bank. Commented Jun 23, 2018 at 4:39
  • 1
    You are, once again, incorrect. XHR has a property called withCredentials that will cause your cookies to be sent on the cross-origin request. (This is technically a CORS feature, but then, so is cross-origin XHR at all.) This does not cause a CORS pre-flight; your request will go out, as specified, immediately (though you won't see the response). Of course, you don't need an XHR here - you could just have a <script src="https://yourbank.com/transfer/?toAccount=attackersaccount&amount=1000USD"></script> and it would generate a GET request with cookies - which is why there's no pre-flight.
    – CBHacking
    Commented Jun 23, 2018 at 21:40
  • 1
    Seriously, go read the answers to the "possible dupe" link (security.stackexchange.com/questions/97825/…), and possibly also do some research on stuff like "CORS pre-flight". You are giving people incorrect information that would, if believed, lead to them making very bad security decisions.
    – CBHacking
    Commented Jun 23, 2018 at 21:44
  • 2
    For anybody who doesn't check the edit history: the original version of this answer, which was current for all comments before this one, used an HTTP GET request (to https://yourbank.com/transfer/?toAccount=attackersaccount&amount=1000USD), not even a POST and definitely not using JSON. WITH THAT SAID, the current example and explanation are correct, provided that the XHR from evil.com specified a content type of application/json as in the quoted block (leaving the default content type, or specifying text/plain, would not trigger a pre-flight; the response would simply be ignored).
    – CBHacking
    Commented Jun 25, 2018 at 9:33

Not the answer you're looking for? Browse other questions tagged .