I often get both of these concepts confused, and apparently so do a lot of other people. It's a pretty important concept to be understood by web developers and security engineers, so hopefully this clears things up.
First, an introduction
Cross Origin Resource Sharing (CORS) and Content Security Policy (CSP) are used by web applications to control what data can be loaded on a page, and what data other pages can load from it (see, it's already gotten confusing). It is vital to have CORS and CSP configured correctly from a security perspective, because it would otherwise be difficult to trust the integrity of a web page (if any scripts can be loaded) but also the confidentiality of your own data on a web page if it can be loaded by anyone.
When learning about CORS and CSP, it's important to understand what's going on from both perspectives (requestor and requestee), because as a host you will be playing both positions. To drive this message home, I'll be referring to YOUR website which is ✨Super Secure Sally✨, and MY website which is 🤡Really Risky Ricky🤡.
Firstly, what is CORS?
To quote MDN Web Docs
"Cross-Origin Resource Sharing (CORS) is a HTTP-header based mechanism that allows a server to indicate any origins other than its own from which a browser should permit loading of resources."
You can view what CORS policies are set on a particular host/page by viewing the response headers. The main header we are concerned with is:
Access-Control-Allow-Origin
This response header dictates which domains are allowed to receive the requested data.
Before making a request from another origin, it's common to make a preflight OPTIONS request to determine whether the request will be successful. In that case, the requestor will provide the request headers:
Origin
Access-Control-Request-Method
Access-Control-Request-Headers
This requestee will then send a response as to which origins, methods and headers are allowed when requesting the resource:
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Let's explore this using examples.
Sally wants to load a resource from Ricky
Sally (you) wish to load a resource on Ricky's domain. Luckily, Ricky has very relaxed CORS settings and will allow anyone to request resources.
Ricky's Access-Control-Allow-Origin
header contains a wildcard value *
which means anyone can load this resource from his website. This is a super dangerous setting to have, especially if the data is sensitive and confidential.
Ricky wants to load a resource from Sally
Ricky wants to now load a resource from Sally. Sally's data is extremely confidential and the most secure CORS settings have been configured to ensure only she can make requests for that data.
Something in between
Say if Sally changed her mind and she wanted Ricky to be able to successfully request data from Sally. In that case Sally's response header should say:
Access-Control-Allow-Origin: http://ricky.com
In Summary
When it comes to CORS, you want to be conscious of what resources you can load, and what resources other people can load from you.
Next, lets chat about CSP
The goal of CSP is to protect against Cross-Site Scripting (XSS) attacks by dictating which scripts should be trusted and which shouldn't. When a browser tries to run a script from an unknown source, CSP will block it unless it is on the list of trusted sources. If no CSP is provided, then a site will default to using the "Same-Origin Policy" (SOP).
The Content-Security-Policy
response header contains rules for that request. The CSP can restrict things like:
-
default-src
: the fallback for all resources being loaded if no other rule is set. -
script-src
: restricts which inline scripts can be run. -
style-src
: restricts inline styles from being applied. -
media-src
: restricts audio and media files from being loaded. -
img-src
: restricts which images can be loaded.
There are plenty of other options to use. You can see them on this Mozilla Developer Page.
At this point, I'm going to introduce a new site 😈 Evil Eddie 😈.
For each of our scenarios, Eddie is going to intercept a request/response to Sally and Ricky's website and try and inject an evil script off his website onto Sally/Ricky's webpages so that it executes the malicious script.
Evil Eddie attacks Super Secure Sally
Sally's CSP header looks like this:
Content-Security-Policy: default-src 'self' charlies-cookies.com
.
When Eddie tries to attack Sally's website, his script is not loaded because it is blocked by Sally's CSP which says only scripts from her website and her friend Charlie's website will be loaded.
Evil Eddie attacks Really Risky Ricky
Ricky's CSP header looks like this:
Content-Security-Policy: default-src 'self'; script-src *; img-src *.ricky.com
Eddies attack is successful on Ricky's page, because Ricky has used the wildcard *
character which allows scripts to be loaded from all origins.
In Summary
Be careful with listing which sites your website can load resources from and only update your allow-list if it's really REALLY necessary. It's also super important to chose resources from secure sites that wouldn't be susceptible to XSS attacks themselves.
Okay... but after all of this, CSP and CORS still sounds almost the same?
Yeah look.. they can be confusing concepts to distinguish because there seems to be a lot of overlap. The way I look at it (in order to help separate the two in my brain) is to consider "what do you have control over". As a host, there are three (general) scenarios:
- You want to request a resource from another site ~ What CORS policies do they have in place?
- Another site wants to request a resource from your site ~ what CORS policies do you have in place?
- You want to load a resource (script, image, whatever) from another site ~ does your Content Security Policy allow you to load resources from that domain?
Have you got any handy ways of remembering the difference between CSP and CORS? I'd love to hear them.
Top comments (6)
Excellent article. Thank you.
Super article. Thanks for making it easy to understand the difference.
Both CORS and CSP are security measures to solve the cross origin resource sharing issues in the browser.
Now it is clear what is the scope of CORS and CSP.
The handy way to remember is "CORS is solved by the provider and CSP is solved by the consumer".
To resolve CORS, the provider of the resource (cross origin resource) has to specify, in the response header, who is allowed to access its (provider) resources.
To resolve the CSP, the consumer has to specify, in the response header, from where it is allowed to consume the resources.
Awesome article, thanks you finally helped me understand the difference :)
Excellent! Thank you!
Looks awesome Alexander! Keen to have a play around with it 😊
Clean one!