When adding an on error event listener, typically you will receive an ErrorEvent object full of details (message, line, column, etc) about the error message; however, when an error is thrown from a cross origin script, all you get is the "Script error." message. From my understanding, this is done for security reasons.
I am running into some problems because of this restriction. I have am running cross-origin scripts (not my scripts, they could come from anywhere, I don't control them, total randomness here) within an IFrame element where I have added an on error event listener and the "sandbox" attribute.
My goal was to report and sandbox violations that happened to the top level page. So for example, if the sandbox doesn't allow pop-ups. Within the console window an error message is displayed that says something like "Pops are not allowed in a sandboxed environment". The onerror picks up on the error, but when you inspect the message, it always says "Script error".
Is there a different way for me to catch these uncaught/unsafe error messages?
My goal is to parse out the messages to see which sandbox violations are being thrown for logging. This method will not work, because any uncaught error message within the IFrame will get translated to the same message, which could lead to false positives. For example, someone does throw new Error('test')
and now there is no way for me to tell if it was a sandbox error or a script error.
If the Javascript error message is "Script error.", there is no way to extract the actual error message via Javascript. While the user can examine their browser console to see the error details, the cross-origin error details will not be exposed to your Javascript in any way, for security reasons.
To mitigate this, if at all possible, suggest that users use libraries from sites which do not have CORS restrictions. A site that hosts a library needs to have both
access-control-allow-origin: *
access-control-expose-headers: *
in order to catch errors thrown in scripts hosted by that site. For example:
<script src="https://cdn.jsdelivr.net/npm/babel-standalone@6.10.3/babel.min.js"></script>
Because jsdelivr has both of those headers, errors thrown will be viewable. (Forgive the stack snippet hacks, but it demonstrates the issue:)
-->
</style>
<script src="https://cdn.jsdelivr.net/npm/babel-standalone@6.10.3/babel.min.js"></script>
</script>
</head>
<body>
<script src="/scripts/snippet-javascript-console.min.js?v=1"></script>
<script type="text/babel">Invalid syntax
</style>
<!--
If the library comes from a site without both of those headers, the error will be opaque. For example, this snippet is identical to the above, except that the link is to a site without access-control-expose-headers: *
:
-->
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.10.3/babel.min.js"></script>
</script>
</head>
<body>
<script src="/scripts/snippet-javascript-console.min.js?v=1"></script>
<script type="text/babel">Invalid syntax
</style>
<!--
If you have no control at all over which library links the users use, there's nothing you can do to get access to the opaque errors, unless you can get them to install a custom browser extension (which has escalated privileges), or something like that.