jquery: Unhandled http error while appending an html with script element

Description

I have an application where the customers can load arbitrary HTML code which is then loaded into the DOM via jQuery. A customer had a copy and paste error which linked to an non existing js file. This lead to an 404 but nevertheless jQuery pushes the return value (error HTML page) into a HTMLScriptElement text property. This leads to an exception:

Uncaught SyntaxError: Unexpected token <
at DOMEval (jquery-3.3.1.js:111)
at Function.globalEval (jquery-3.3.1.js:345)
at text script (jquery-3.3.1.js:9640)
at ajaxConvert (jquery-3.3.1.js:8784)
at done (jquery-3.3.1.js:9255)
at XMLHttpRequest.<anonymous> (jquery-3.3.1.js:9548)
at Object.send (jquery-3.3.1.js:9600)
at Function.ajax (jquery-3.3.1.js:9206)
at Function.jQuery._evalUrl (jquery-3.3.1.js:9367)
at domManip (jquery-3.3.1.js:5759)

Minimal test case

Put this HTML onto an webserver:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <title>Title</title>
	<script>
	function clickme() {
			var jBody = $(document.body);
			jBody.append('<script type="text/javascript" src="notexisting.js"><'+'/script>');
	}
	</script>
  </head>
  <body>
        <button onclick="clickme()">Click</button>
  </body>
</html>

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 16 (12 by maintainers)

Commits related to this issue

Most upvoted comments

I wasn’t sure about what changes were necessary and had been exploring extensions to ajax converter and dataFilter arguments, but in the end came to a much simpler conclusion: rather than relying upon them, we should update jQuery._evalUrl to evaluate responses manually:

return jQuery.ajax( {
	url: url,

	// Make this explicit, since user can override this through ajaxSetup (#11264)
	type: "GET",
	dataType: "text",
	cache: true,
	async: false,
	global: false,
	"throws": true,

	// Only evaluate the response if it is successful (gh-4126)
	success: function( text ) { jQuery.globalEval( text ); }
} );

The HTML Standard requires an “ok status” as defined by Fetch to be “in the range 200 to 299, inclusive”.

Yup, that makes sense. I guess the only way the browser would try to execute is if the response code did not match the response content.

@timmywil We’re not doing what the browser does. As @HolgerJeromin mentioned, if a browser hits an error page when downloading a script it will display an error message in the console but will not try to evaluate the error page as a script. Meanwhile, we invoke the converter even for error responses and the converter calls globalEval on the response.

I think it’s a bug we should fix. Moreover, if the 404 page returns something parseable as JavaScript this may influence the page behavior randomly. Granted, such a response is unlikely but possible so in edge cases, this bug may have important consequences.