3

Edit: if there is another way of disabling javascript with javascript - I'm all ears.

I'm trying to disable javascript using javascript, by "injecting" a

<meta http-equiv="Content-Security-Policy" content="script-src 'none' ">

Into the element. The element IS added, according to Firefox dev tools -> inspector, but is ignored. Why, and how can I make a browser to "notice" it?

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- 
      yes, this works, but I want to do this dynamically
      <meta http-equiv="Content-Security-Policy" content="script-src 'none' ">
    -->
  </head>

  <body>
    Just some javascript for tests, I hoped this will stop working, 
    when I'll call the  disableJavaScript() function below. But it
    doesn't stop    
    <script>
      var x =  0;
      setInterval(function(){
        console.log(x++);
      }
      ,1000);
    </script>

    Inserting the meta element:

    <script>
    function disableJavaScript(){
        var newMetaNode = document.createElement("meta");
        newMetaNode.setAttribute('http-equiv','Content-Security-Policy'); 
        newMetaNode.setAttribute('content',"script-src 'none'");
        var headElem = document.getElementsByTagName('head')[0];
        headElem.appendChild(newMetaNode);
      }

    //calling the function after 3 seconds:
    setTimeout(function(){
      disableJavaScript();  
    },3000)  

    </script>

  </body>

</html> 
konrados
  • 1,047
  • 8
  • 21
  • 2
    What's the use case…? Why do you want to disable Javascript? Why can't you add the meta header statically? – deceze May 12 '17 at 00:37
  • 1
    Use a blocking version of setTimeout(): http://stackoverflow.com/a/39914235/2104879 – mertyildiran May 12 '17 at 00:37
  • 1
    Throwing an error stops the current process, but it still doesn't stop `setTimeout`, `setInterval` and ajax requests. – Richard Yan May 12 '17 at 00:38
  • 3
    @mertyildiran No. Nope. Nein. If you have a blocking *anything*, the entire browser UI will be unresponsive. Also, that's not a "blocking setTimeout". – deceze May 12 '17 at 00:39
  • 1
    @deceze oh, you are right sorry. – mertyildiran May 12 '17 at 00:40
  • @deceze and others - thank you very much for the comments. I want to create a Firefox/Chrome/etc extension (addon) which can be used to disable/enable javascript on only one, *current* tab. All extensions I know can do that browser-wide, for all the tabs, simply by setting a global browser's option like "enable_javascript" to false. I don't need that. Say I'm working on an app, I have many tabs opened including this app, and I want to temporarily turn off the javascript on this one particular app (tab). Not entirely. – konrados May 12 '17 at 00:44
  • 2
    Can’t a user already disable JavaScript per-tab just by opening browser devtools on the tab and choosing *Disable JavaScript*? – sideshowbarker May 12 '17 at 01:11
  • @sideshowbarker - way too many clicks and it takes space (the entire dev tools :) But OK, I see your answer below, I'll try to investigate it. – konrados May 12 '17 at 01:32
  • Browser devtools in Firefox and Chrome already provide a way to disable JavaScript per-tab. So rather than trying to set `Content-Security-Policy` to do it, or some other workaround, you could look through the devtools sources for the devtools disable-JavaScript feature and figure out what mechanism that devtools feature is using to disable JavaScript. I believe extensions usually have access to use any (privileged) mechanisms that devtools can use, so I would think you could write an extension that just does it the same way devtools does. – sideshowbarker Oct 05 '18 at 01:54
  • @sideshowbarker I don't understand why you removed your answer. "Your approach is not fit for this problem, do not try to fit it to the problem and seek an entirely different solution" is perfectly fine as an answer. – Oleg V. Volkov Jan 13 '22 at 12:24

1 Answers1

1

script-src policy does NOT disable JavaScript. It disables loading of new content referenced with <script> tags that are inserted into a document after you declare your policy.

Policies in meta elements are not applied to content which precedes them.

https://w3c.github.io/webappsec-csp/#meta-element

You can see it working perfectly fine with new content and stopping output in console after a few successful calls if you change your "testing" tag to:

<script>
  var x =  0;
  setInterval(function(){
    var newNode = document.createElement("script");
    var newText = document.createTextNode("console.log("+ x++ +")")
    var bodyElem = document.getElementsByTagName('body')[0];
    newNode.appendChild(newText)
    bodyElem.appendChild(newNode);
  }
  ,1000);
</script>

CSP does not have means to somehow retroactively "cancel" content that was loaded before it was enforced. You need to look in browser-specifc extension API.

Oleg V. Volkov
  • 21,719
  • 4
  • 44
  • 68