Fix base64 data URI scripts function So I noticed Chrome has quirky behaviour when it encounters script tags whose src is a base64 value. I decided to write a quick jQuery method that is supposed to work around it:

jQuery.extend({

    /**
     * Takes a script decodes the base64 src, puts it into the body of the script tag,
     * then puts it in whatever parent specified.
     *
     * @requires https://plugins.jquery.com/base64/
     * 
     * @param  {Object} script The script tag that should be manipulated
     * @param  {Object} parent The parent element to append the final script tag to.
     * 
     * @return {Object}        The script tag in question
     */
    importBase64Script : function ( script, parent ) {

        // Check for base64 library
        if ( typeof $.base64 === 'undefined' )
            throw 'No $.base64 found!';

        // Sanitize our script var
        // Normalize our script object
        script = ( script instanceof jQuery ? script : $(script) );

        // Check if it is a script tag
        if ( script[0].tagName !== "SCRIPT" )
            throw "Not a script tag";

        // Set default parent value
        parent = parent || $('head');
        // Normalize our parent var
        parent = ( parent instanceof jQuery ? parent : $(parent) );

        // We're gonna extract the base64 value
        var re        = /data:[a-z]+\/[a-z]+;base64,([0-9a-zA-Z\=\+]+)/,
        base64Content = script.prop('src').match(re)[1],
        scriptContent = $.base64.decode( base64Content );

        // Drop the decoded javascript into the contents of the script tag
        script.html( scriptContent );
        // Clear src value
        script.prop('src','');

        // Append it to the parent
        parent.append(script);

        return script;

    }
});


I tested a few of the conditions on JsPerf to see which is better performance wise. Granted, I didn't do a full sweep on every browser.

Any suggestions that anybody could make?
Watch out!

jQuery is full of secrets. html method is not just a simple wrapper around innerHTML property.

Possible fail condition:



var src = `if ("&lt;x/&gt;" !== "&lt;" + "x" + "/" + "&gt;") {
  console.log("Math gone wrong.");
}`;

$("&lt;script&gt;").html(src).appendTo(document.head)
&lt;!-- latest jQuery --&gt;
&lt;script src="https://code.jquery.com/jquery-3.3.1.min.js"&gt;&lt;/script&gt;




Let's see what exactly is happening here:



console.log($("&lt;i&gt;").html("&lt;x/&gt;")[0].innerHTML)
&lt;!-- latest jQuery --&gt;
&lt;script src="https://code.jquery.com/jquery-3.3.1.min.js"&gt;&lt;/script&gt;




jQuery html method replaces &lt;x/&gt; with &lt;x&gt;&lt;/x&gt;. I guess it is perfectly valid for some HTML, but it fails with our JavaScript input.

The π robbery

Let's try to exploit this with malicious input and steal some valuable data:



var src = `var username = "Kevin &lt;x\";alert(Math.PI);\"/&gt; Mitnick";`;

$("&lt;script&gt;").html(src).appendTo(document.head);
&lt;!-- latest jQuery --&gt;
&lt;script src="https://code.jquery.com/jquery-3.3.1.min.js"&gt;&lt;/script&gt;




I suggest you to carefully check jQuery html source code.

Also you may replace it with plain old innerHTML.