Removing all script tags from html with JS Regular Expression

jQuery uses a regex to remove script tags in some cases and I'm pretty sure its devs had a damn good reason to do so. Probably some browser does execute scripts when inserting them using innerHTML.

Here's the regex:

/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi

And before people start crying "but regexes for HTML are evil": Yes, they are - but for script tags they are safe because of the special behaviour - a <script> section may not contain </script> at all unless it should end at this position. So matching it with a regex is easily possible. However, from a quick look the regex above does not account for trailing whitespace inside the closing tag so you'd have to test if </script    etc. will still work.


Attempting to remove HTML markup using a regular expression is problematic. You don't know what's in there as script or attribute values. One way is to insert it as the innerHTML of a div, remove any script elements and return the innerHTML, e.g.

  function stripScripts(s) {
    var div = document.createElement('div');
    div.innerHTML = s;
    var scripts = div.getElementsByTagName('script');
    var i = scripts.length;
    while (i--) {
      scripts[i].parentNode.removeChild(scripts[i]);
    }
    return div.innerHTML;
  }

alert(
 stripScripts('<span><script type="text/javascript">alert(\'foo\');<\/script><\/span>')
);

Note that at present, browsers will not execute the script if inserted using the innerHTML property, and likely never will especially as the element is not added to the document.


Regexes are beatable, but if you have a string version of HTML that you don't want to inject into a DOM, they may be the best approach. You may want to put it in a loop to handle something like:

<scr<script>Ha!</script>ipt> alert(document.cookie);</script>

Here's what I did, using the jquery regex from above:

var SCRIPT_REGEX = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi;
while (SCRIPT_REGEX.test(text)) {
    text = text.replace(SCRIPT_REGEX, "");
}