“Script Error”: The arch nemesis of JavaScript error monitoring. As soon as you start monitoring client-side problems, it emerges. It cloaks the true nature of your front-end errors behind its veil of obscurity.
You’ll need to deal with it if you want a comprehensive front-end error tracking solution.
Analysis
Script Error
is a symptom of a Same-Origin Policy violation in the browser.
The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. Same-origin Policy is used as a means to prevent some of the Cross-site Request Forgery attacks.
When your web application loads a JavaScript file from another origin, that script is subject to the restrictions of the Same-Origin Policy. The restrictions include error obfuscation when exposing the error to the global listeners: window.onerror
and window.addEventListener('error')
.
This browser policy aims to prevent information leaking between domains that could allow Cross-Site Request Forgery attacks. The policy is enforced in all relevant browsers, including all versions of Chrome, Firefox, Safari, Opera, and Internet Explorer.
For example, let’s say your application records errors from window.onerror
and loads a CDN-hosted AngularJS. Whenever an error is emitted from Angular, the error will be recorded as simply Script Error
with no mention of the original message, the angular.js file, or the stack trace.
Consider how Chrome exposes a JavaScript Error. When an error occurs, it evaluates the security origin of the file. If it violates the policy, the error is simply overwritten with empty values.
bool ScriptExecutionContext::dispatchErrorEvent( const String& errorMessage, int lineNumber, const String& sourceURL) { ... if (securityOrigin()->canRequest(targetUrl)) { message = errorMessage; line = lineNumber; sourceName = sourceURL; } else { message = "Script error."; sourceName = String(); line = 0; } ... RefPtr<ErrorEvent> errorEvent = ErrorEvent::create(message, sourceName, line); target->dispatchEvent(errorEvent); ... }
Even when a JavaScript error is obfuscated by the Same-Origin Policy, Chrome’s debugger will display the original error information. Therefore, you may not be aware that errors are being obfuscated until you begin monitoring them.
You may encounter Script Error
if you load at least one JavaScript asset from another domain, such as a CDN or third-party. Note that the script may be loaded by JavaScript at runtime, so you’ll need to check the network requests in the debugger to be sure.
Solution
We can side-step the Same-Origin Policy using Cross-Origin Resource Sharing (CORS). CORS is most commonly used to address a different violation in the Same-Origin Policy: allowing cross-domain AJAX calls against external API’s. It can also be used to load JavaScript assets exempt from error obfuscation.
Each server, CDN, or vendor that you load JavaScript assets from needs to serve the request with the CORS headers:
Access-Control-Allow-Origin: YOUR_DOMAIN | *
The wildcard *
can be used instead of a domain if you want to allow the file to be loaded from anywhere. There are fantastic resources on how to configure your webserver to add these headers, and most CDNs and vendors will have a mechanism to configure or request them.
From your web application, you can tell the browser to load CORS JavaScript files with the crossorigin
attribute:
<script src=”thirdparty.com/script.js” crossorigin></script>
By default the asset will be requested anonymously. If you want to use CORS authentication, you may also specify credentials on how to load the asset.
Loading assets with CORS is supported in most modern browsers. However, the lack of Internet Explorer support is concerning–especially because of the prevalence of IE-only bugs we tend to encounter.
Browser | Versions | CORS Loading Support |
---|---|---|
Chrome | 30+ | Yes |
Firefox | 13+ | Yes |
Safari | 7+ | Yes |
Opera | 12.5+ | Yes |
Internet Explorer | N/A | No |
Microsoft Edge | N/A | ? |
CORS loading is definitely worthwhile for the extra context you’ll gather from most browsers. From unsupported browsers, it’s still helpful to listen for Script Error
so you know the specific browsers, pages, and users having problems.
Of course if you just don’t care, you should ignore them and reduce the noise.
TrackJS captures better information about JavaScript errors, even in Internet Explorer. It has deeper DOM inspection to capture more error information and the events that led the user to problems. Get started with a free trial today and fix more bugs.