Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to see what is returned when a remote script is blocked

I'm using Google hosted jQuery in my webapp (//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js) As part of bug diagnostics I have a window.onerror handler which catches any errors I'm not catching locally and lets the server know about them.

So far so good, but... sometimes i get errors like these:

"Script error.","Error loading script","Unexpected token <"

My assumption is that the Google CDN is blocked in these cases (for whatever reason). I do have a local fallback for jQuery, that I'm fairly sure is working well, but I would like to find out what's being returned so that I can test my assumptions and maybe get some of these users on a white list for Google CDN (if it's company firewall blocking it).

But so far I haven't been able to figure out how to retrieve the returned content. Can't retrieve innerText of a SCRIPT tag if it's a file, can't do an ajax request because of cross-domain policy, etc.

Does anyone have any ideas about how this would be possible?

like image 389
Pyro979 Avatar asked Jan 02 '13 15:01

Pyro979


1 Answers

It simply isn't possible to get the content of any file referenced by a <script> tag. This is with good reason: doing so would allow you to circumvent XHR's Same Origin Policy.

Consider:

<script src="https://www.example.com/private/api/getAuthToken" id="s"></script>

If you could access the text of the respnse, you'd be able to do this:

var stolenAuthToken = $('#s').text();

That's obviously bad. Therefore, you're never allowed to read the content of something brought in by <script> tags.

Your particular situation is complicated by a relatively recently introduced change where errors in cross-origin scripts do not report any useful information to your page's onerror handler. (Essentially, this was done to patch an information disclosure security hole that allows a malicious site to infer whether you're logged in to some well-known sites, among other things.)

This means that you get no useful information about errors from CDN-hosted script, so another change was made to allow the use of CORS for a CDN (or other non-same-origin) server to opt in to allowing full error details to pass to an onerror handler.

We (Facebook) need a mechanism for disabling the window.onerror muting behavior implemented in #363897. Our static script resources are served on a CDN under a different domain from the main site. Because these domains differ we're falling afoul of the x-domain logic that prevents us from gathering useful information about browser errors.

This "feature" has been widely enough adopted in in the wild (in Firefox and Webkit browsers) that the majority of uncaught exceptions we see in production now have no actionable information in them.

The crossorigin attribute (originally intended for <img>) allows you to specify that a resource should be loaded with CORS rules. It has been implemented by Mozilla, WebKit, and Chrome.

<script src="http://example.com/xdomainrequest" crossorigin="anonymous"></script>

Unfortunately for you, in my testing, I found that the Google CDN does not send CORS headers.

GET http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js HTTP/1.1
Host: ajax.googleapis.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://fiddle.jshell.net/josh3736/jm2JU/show/
Origin: http://fiddle.jshell.net
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 200 OK
Vary: Accept-Encoding
Content-Type: text/javascript; charset=UTF-8
Last-Modified: Tue, 13 Nov 2012 19:53:02 GMT
Date: Wed, 02 Jan 2013 22:54:25 GMT
Expires: Thu, 02 Jan 2014 22:54:25 GMT
X-Content-Type-Options: nosniff
Server: sffe
Content-Length: 93637
X-XSS-Protection: 1; mode=block
Cache-Control: public, max-age=31536000
Age: 169036

...

Note the presence of the Origin header in the request (indicating a CORS request), and the absence of an Access-Control-Allow-Origin header in the response. Thus, even if you put the crossorigin attribute, the CORS check will fail, and your scripts will receive scrubbed error details.

There is a three-year-old issue to enable CORS on the Google CDN server. I wouldn't hold my breath.


tldr: If you want meaningful error messages, you must host all JavaScript yourself, on the same origin.

like image 75
josh3736 Avatar answered Nov 14 '22 23:11

josh3736