I want to serve my JavaScript scripts from a CDN like cloudflare.
Now my scripts communicate with my app server via ajax. Wouldn't the same-origin policy restrictions come into play when I load these scripts from a CDN?
Let's say my app is on the domain:
http://app.com
And I load my scripts from
http://cdn.com/xyz/all.js
Now, since my scripts are loaded from a different domain than the domain my app is running from, I guess the same origin policy would prevent me from doing ajax communication with my app.
Am I getting something wrong?
No, it will work. That's why JSONP works. The "origin" of the script is the page it is executed in, not where it comes from.
As you asked for it, here's a reference (I couldn't find any better, but Crockford is well known)
The src attribute, surprisingly, is not constrained by the Same Origin Policy. This means that a script element can be created which can go to any server, fetch a script, and execute it. If the script causes the delivery of JSON-encoded data, then this is a very useful thing. Unfortunately, there is no way to constrain the script or to inspect it before it executes. It runs with the same authority as scripts from the page. So the script can access and use its cookies. It can access the originating server using the user's authorization. It can inspect the DOM and the JavaScript global object, and send any information it finds anywhere in the world. The Script Tag Hack is not secure and should be avoided.
http://javascript.crockford.com/script.html
Not really a reference: If this wouldn't work, nobody could include jQuery from Google's CDN and then use it's $.ajax method.
Related
What data can external javascript fetch from a website, if it placed in website's <head> tag? For example cookies, local storage? How can it harm a website's security?
Pretty much everything.
The origin of a script is determined by the page its <script> element appears on. The external script can access the same things as a script you wrote yourself (including using Ajax to make HTTP requests to the same origin).
How can it harm a website's security?
You've given them all the keys and turned off the alarms.
I know by default the HTML page on other domains can't access my images, videos. They can only show them. But sadly, they can still run my scripts. If my script exposes some variables to the global scope, then the internal logic may be known by others.
I have a private website that others can't visit. Only I can visit it by sending a token in the Cookie to the server. If the token isn't included in the Cookie, every request will cause a 500 server error response. This is secure because everything is on HTTPS.
But unfortunately, I find this isn't very safe on my own machine, because after I visit my site and then visit a malicious site, this malicious site can use the following method to run my script:
<script src="https://my-website.com/main.js"></script>
That's because the Cookies of my website on my machine will be sent to my server as 3rd-party Cookies.
How to prevent that? Can access-control-allow-origin do so?
P.S. I don't want to disable all 3rd-party cookies in browser settings. Cookie's SameSite also doesn't make sense because only Chrome support it now.
There are a number of imaginable ways to prevent other sites from using the script element to run copies of scripts from your site in their sites, but CORS isn’t one of them.
Browsers are where the same-origin policy (SOP) is enforced and browsers are what block JavaScript running in Web apps from being able to use responses from cross-origin requests.
But browsers don’t use SOP/CORS when a Web app uses the script element to embed some JavaScript. Specifically, browsers don’t check that the script is served from the other site with an Access-Control-Allow-Origin header, which is the foundation of the whole CORS protocol.
So CORS is definitely not a solution to the problem you seem to want to solve.
But unfortunately, I find this isn't very safe on my own machine, because after I visit my site and then visit a malicious site, this malicious site can use the following method to run my script:
<script src="https://my-website.com/main.js"></script>
But if that site embeds your script in theirs that way, it runs within their origin, not yours. It runs there as a trusted script with all the same privileges of any script they’ve written themselves.
In that scenario, the other site is the one taking a security risk—because you can at any time change your https://my-website.com/main.js script to do anything you want at their site.
That is, by embedding your script that way, the other site gives your script programmatic fully-trusted access to do anything it wants at their entire origin—gifting you an XSS opportunity.
I'm a bit confused on how JavaScript is able to load external libraries. Is it doing a GET request to the url I specify in the script tags? Does the browser handle the storage of the library or is it kept somewhere in the DOM?
It seems like most things that the browser might be doing with loading external libraries would violate the same-origin policy. Is there any extra security modern browsers enforce when loading scripts from external sites? Is it possible to load an external library and then print its source to the screen?
Thanks!
I'm a bit confused on how JavaScript is able to load external libraries.
JavaScript has no native means to load libraries. That is a feature provided by the host environment (such as a browser or node.js).
Is it doing a GET request to the url I specify in the script tags? Does the browser handle the storage of the library or is it kept somewhere in the DOM?
The browser will make a GET request, load the script into the JavaScript environment for the viewport, but only keep the HTMLScriptElement DOM Node in the DOM.
It seems like most things that the browser might be doing with loading external libraries would violate the same-origin policy.
The same origin policy is designed to protect non-public data on third party sites. Scripts aren't data (although they can be written so they have embedded data in them, JSON-P depends on this as a way to avoid the same origin policy).
Is there any extra security modern browsers enforce when loading scripts from external sites?
No
Is it possible to load an external library and then print its source to the screen?
No (although you can use XHR to make a separate HTTP request to get the script source — which is subject to the same origin policy).
I'm reading about the same origin policy. I understand that the js on my page should not have access to methods (and more) defined in a js resource on a different domain. However, I must be misreading this. In my website, I have a script reference to the jquery library at the code.jquery.com domain,
<script src='http://code.jquery.com/jquery-1.8.2.js'></script>
and everything in that library is available to the js scripts on my site.
So, what am I misunderstanding here?
The same-origin-policy says that you are not allowed to use objects etc. declared in another domains i.e. in an iframe.
It does not forbid to load a script from a domain and run the code locally. The variables in the jquery script are not from another domain, you just loaded the source code from there.
Same Origin Policy affects iframes and XHRs, img and canvas, among other things.
Pointing a script src to a different host, protocol or port is not in violation with this. This is useful, as we can use a CDN to serve the files and use JSONP for data transfer (before CORS can be used everywhere - thanks < IE8).
I have a JS file that puts an iframe on every site its on.
both the JS and the iframe location comes from the same domain, mine.
Can I somehow communicate from within the iframe to the outside script,
which isn't running on my domain, but is called from it?
I know about JSONP but i'm looking for a better way if possible
It's very simple. The location of the document needs to be served from the same domain as the location of the script. Otherwise, the script will get "Access Denied" error.
If you are supplying a script for other people to use, then you could have them load easyXDM which would allow your script to communicate with the document loaded in the iframe (if it also has the easyXDM library set up).
You would also have to require them to host a simple html file on their domain in case easyXDM cannot use postMessage and has to resort to using the hash/fragment solution.
Demos of this can be viewed here