Can I ask a browser to not run <script>s within an element?

Solution 1:

YES, you can :-) The answer is: Content Security Policy (CSP).

Most modern browsers support this flag, which tells the browser only to load JavaScript code from a trusted external file and disallow all internal JavaScript code! The only downside is, you can not use any inline JavaScript in your whole page (not only for a single <div>). Although there could be a workaround by dynamically including the div from an external file with a different security policy, but I'm not sure about that.

But if you can change your site to load all JavaScript from external JavaScript files then you can disable inline JavaScript altogether with this header!

Here is a nice tutorial with example: HTML5Rocks Tutorial

If you can configure the server to send this HTTP-Header flag the world will be a better place!

Solution 2:

You can block JavaScript loaded by <script>, using beforescriptexecute event:

<script>
  // Run this as early as possible, it isn't retroactive
  window.addEventListener('beforescriptexecute', function(e) {
    var el = e.target;
    while(el = el.parentElement)
      if(el.hasAttribute('data-no-js'))
        return e.preventDefault(); // Block script
  }, true);
</script>

<script>console.log('Allowed. Console is expected to show this');</script>
<div data-no-js>
  <script>console.log('Blocked. Console is expected to NOT show this');</script>
</div>

Note that beforescriptexecute was defined in HTML 5.0 but has been removed in HTML 5.1. Firefox is the only major browser that implemented it.

In case you are inserting an untrusted bunch of HTML in your page, be aware blocking scripts inside that element won't provide more security, because the untrusted HTML can close the sandboxed element, and thus the script will be placed outside and run.

And this won't block things like <img onerror="javascript:alert('foo')" src="//" />.

Solution 3:

Interesting question, I don't think it's possible. But even if it is, it sounds like it would be a hack.

If the contents of that div are untrusted, then you need to escape the data on the server side before it is sent in the HTTP response and rendered in the browser.

If you only want to remove <script> tags and allow other html tags, then just strip them out of the content and leave the rest.

Look into XSS prevention.

https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet