CORS, or cross origin resource sharing, is one of the most misunderstood concepts of web security. Many know what it is, some know why we need it, and only a few know its limitations.

This post will go through some of the key concepts of CORS, and emphasize why we need it for the modern web.

What is CORS?

The best way to explain it is through an example.

First, Open up your browser, and navigate to stackoverflow.com.

Next, open up your browsers console, and run this snippet :

fetch('http://stackoverflow.com').then(res => console.log(res))

You should see this nice clean response returned back, like this :

console

All fine and dandy! We used the browsers fetch API to get the content of stackoverflow’s webpage, by making an http request. Now, lets try getting wikipedias homepage instead :

fetch('http://wikipedia.org').then(res => console.log(res))

If you run this, you should see an error like this :

console

It looks like we’re not allowed to get the details of wikipedias homepage. In fact, if you make a request to any origin other than stackoverflow, you will see this error. However, if you open your console on any wikipedia page , and make a request for wikipedias homepage, you would get a good response once again.

To put it simply, it is forbidden to make a request to any origin, other than the one your code is running in, unless otherwise allowed by its server. This is called the same origin policy.

Almost all urls serving their resources will have a CORS policy. By default, if there is no policy, it is assumed that CORS is disabled. But why would anyone want to disable access to their origin? This brings us to our next section :

Why isn’t CORS allowed?

It might seem harmless to allow requests to another origin. After all, that url would receive millions of other requests from unknown sources anyways. The problem lies in the way browsers work.

All requests sent from your browser are treated the same. The server receiving them cannot distinguish the circumstances under which they were sent. This means that if you were logged in on one site, and browsing another (malicious) site, and http request made by that sites code to the first site, would be treated as a genuine request from you.

This means that this :

console

Could turn into this :

console

How strictly is CORS enforced?

This is often the most misunderstood aspect of CORS. It’s quite contradictory that one cannot make a simple http request from their own browser to a different origin, but you can make the same request using something like postman or curl from the command line.

If these kind of requests cannot be made from the browser, how are they so easily made through these third party applications, which can be equally as malicious?

CORS isn’t actually enforced by the server, but rather the browser. The server simply states the sites that are allowed cross origin access through the Access-Control-Allow-Origin header in all its responses. It is up to the browser to respect this policy.

Of course, all popular browsers in use today do follow the same origin policy. Some applications like postman, curl do not respect this policy, because they are meant to be used as developer tools, and as such it is expected that the people using these tools know what they’re doing.

console

Caveats and exceptions

1.Fetch can make cross origin requests : Well… kind of. There is a no-cors mode that can be made use of to make cross origin requests with fetch, like this

fetch('http://wikipedia.org', {
  mode: 'no-cors'
}).then(res => console.log(res))

However, you won’t be able to read this response for the same reasons as before. This is only useful if you want to do things like response forwarding.

2.CORS can be stricter than usual : The above comic is not always true. If a server really does not want other clients to receive a response, it can disable CORS for non browser clients as well. This means that you can only make requests from the same origin, and that tools like postman and curl can’t make requests either. Although this is possible, it generally isn’t the case.

If you want to learn more about security on the web, be sure to read my other posts on web security essentials :

XSS (Cross site scripting)
SQL Injection
Password storage
Sessions and cookies
CSRF (Cross site request forgery)
Human Error and UI/UX design