Removing all script tags from html with JS Regular Expression

JavascriptHtmlRegex

Javascript Problem Overview


I want to strip script tags out of this HTML at Pastebin:

> http://pastebin.com/mdxygM0a

I tried using the below regular expression:

html.replace(/<script.*>.*<\/script>/ims, " ")

But it does not remove all of the script tags in the HTML. It only removes in-line scripts. I'm looking for some regex that can remove all of the script tags (in-line and multi-line). It would be highly appreciated if a test is carried out on my sample http://pastebin.com/mdxygM0a

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

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.

Solution 3 - Javascript

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, "");
}

Solution 4 - Javascript

This Regex should work too:

<script(?:(?!\/\/)(?!\/\*)[^'"]|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\/\/.*(?:\n)|\/\*(?:(?:.|\s))*?\*\/)*?<\/script>
 

It even allows to have "problematic" variable strings like these inside:

<script type="text/javascript">
   var test1 = "</script>";
   var test2 = '\'</script>';
   var test1 = "\"</script>";
   var test1 = "<script>\"";
   var test2 = '<scr\'ipt>';
   /* </script> */
   // </script>
   /* ' */
   // var foo=" '
</script>

It seams that jQuery and Prototype fail on these ones...

Edit July 31 '17: Added a) non-capturing groups for better performance (and no empty groups) and b) support for JavaScript comments.

Solution 5 - Javascript

Whenever you have to resort to Regex based script tag cleanup. At least add a white-space to the closing tag in the form of

</script\s*>

Otherwise things like

<script>alert(666)</script   >

would remain since trailing spaces after tagnames are valid.

Solution 6 - Javascript

If you want to remove all JavaScript code from some HTML text, then removing <script> tags isn't enough, because JavaScript can still live in "onclick", "onerror", "href" and other attributes.

Try out this npm module which handles all of this: https://www.npmjs.com/package/strip-js

Solution 7 - Javascript

Why not using jQuery.parseHTML() <http://api.jquery.com/jquery.parsehtml/>;?

Solution 8 - Javascript

You can do this without a regular expression. Simply cast your HTML string to an HTML node using document.createElement(), find all scripts with element.getElementsByTagName('script'), and then just remove() them!

Fun fact: SO's demo does not like it when you create an element with a <script> tag! The snippet below will not run, but it does work at: Full Working Demo at JSBin.com.

var el = document.createElement( 'html' );
el.innerHTML = "<p>Valid paragraph.</p><p>Another valid paragraph.</p><script>Dangerous scripting!!!</script><p>Last final paragraph.</p>";

var scripts = el.getElementsByTagName( 'script' ); // Live NodeList of your anchor elements

for(var i = 0; i < scripts.length; i++) {
  var script = scripts[i];
  script.remove();
}

console.log(el.innerHTML);

This is a much cleaner solution than a regex, imho.

Solution 9 - Javascript

In my case, I needed a requirement to parse out the page title AND and have all the other goodness of jQuery, minus it firing scripts. Here is my solution that seems to work.

        $.get('/somepage.htm', function (data) {
            // excluded code to extract title for simplicity
            var bodySI = data.indexOf('<body>') + '<body>'.length,
                bodyEI = data.indexOf('</body>'),
                body = data.substr(bodySI, bodyEI - bodySI),
                $body;

            body = body.replace(/<script[^>]*>/gi, ' <!-- ');
            body = body.replace(/<\/script>/gi, ' --> ');

            //console.log(body);

            $body = $('<div>').html(body);
            console.log($body.html());
        });

This kind of shortcuts worries about script because you are not trying to remove out the script tags and content, instead you are replacing them with comments rendering schemes to break them useless as you would have comments delimiting your script declarations.

Let me know if that still presents a problem as it will help me too.

Solution 10 - Javascript

Try this:

var text = text.replace(/<script[^>]*>(?:(?!<\/script>)[^])*<\/script>/g, "")

Solution 11 - Javascript

Here are a variety of shell scripts you can use to strip out different elements.

# doctype
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/<\!DOCTYPE\s\+html[^>]*>/<\!DOCTYPE html>/gi" {} \;

# meta charset
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/<meta[^>]*content=[\"'][^\"']*utf-8[\"'][^>]*>/<meta charset=\"utf-8\">/gi" {} \;

# script text/javascript
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/\(<script[^>]*\)\(\stype=[\"']text\/javascript[\"']\)\(\s\?[^>]*>\)/\1\3/gi" {} \;

# style text/css
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/\(<style[^>]*\)\(\stype=[\"']text\/css[\"']\)\(\s\?[^>]*>\)/\1\3/gi" {} \;

# html xmlns
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/\(<html[^>]*\)\(\sxmlns=[\"'][^\"']*[\"']\)\(\s\?[^>]*>\)/\1\3/gi" {} \;

# html xml:lang
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/\(<html[^>]*\)\(\sxml:lang=[\"'][^\"']*[\"']\)\(\s\?[^>]*>\)/\1\3/gi" {} \;

Solution 12 - Javascript

/(?:(?!)<[^<])

Solution 13 - Javascript

You can try

$("your_div_id").remove();  

or

 $("your_div_id").html(""); 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKennedyView Question on Stackoverflow
Solution 1 - JavascriptThiefMasterView Answer on Stackoverflow
Solution 2 - JavascriptRobGView Answer on Stackoverflow
Solution 3 - JavascriptConrad DamonView Answer on Stackoverflow
Solution 4 - JavascriptspaarkView Answer on Stackoverflow
Solution 5 - JavascriptneongrauView Answer on Stackoverflow
Solution 6 - JavascriptShivanshu GoyalView Answer on Stackoverflow
Solution 7 - JavascriptshaoView Answer on Stackoverflow
Solution 8 - JavascriptHoldOffHungerView Answer on Stackoverflow
Solution 9 - JavascriptKing FridayView Answer on Stackoverflow
Solution 10 - Javascriptsurinder singhView Answer on Stackoverflow
Solution 11 - JavascriptdavidcondreyView Answer on Stackoverflow
Solution 12 - JavascriptBlackeningView Answer on Stackoverflow
Solution 13 - JavascriptPooja RoyView Answer on Stackoverflow