1

I have a Tampermonkey userscript that runs at document-start.
How can I check whether inline JavaScript is disabled?

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Six
  • 5,122
  • 3
  • 29
  • 38
  • Insert some code in the page context that should message you back. If you don't get a message (`postMessage`/custom event), then it is not running. However, that does not mean that the some of the JavaScript is disabled. There are some extensions which will selectively disable JavaScript based on different criteria. Are you looking to test for that type of being disabled, or just all JavaScript being disabled? – Makyen Mar 11 '17 at 03:42
  • 1
    I'm specifically looking to test (from a Tampermonkey userscript) whether all inline JavaScript on a page has been disabled, e.g. with a uBlock Origin filter like `*$inline-script,domain=stackoverflow.com`. As Brock Adams mentioned, it appears to do so using the CSP directive `script-src 'unsafe-eval' *`. – Six Mar 11 '17 at 04:23

2 Answers2

0

This is problematic because certain (¿most?) methods of blocking inline JS: (a) don't block unsafeWindow ops and (b) throw exceptions that aren't caught by try ... catch blocks in the Tampermonkey script.

So the following works but if inline JS is disabled, you will see errors like:

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'unsafe-eval' *". Either the 'unsafe-inline' keyword, a hash ('sha256-6BrJXtaiqFeKY4qCquiR3JgWK2KweFWHCvhZWr4tkxA='), or a nonce ('nonce-...') is required to enable inline execution.

in the console. Such errors are annoying but they do not stop the Tampermonkey script.

Working Demo code:

// ==UserScript==
// @name        Test local JS
// @match       *://stackoverflow.com/questions/*
// @run-at      document-start
// @grant       unsafeWindow
// ==/UserScript==

let gbl_InlineJS_Works = true;
try {
    unsafeWindow.TM_youAliveCanary = true;
}
catch (zError) {
    console.log ("Local JS fails: " + zError);
    gbl_InlineJS_Works = false;
}

if (gbl_InlineJS_Works) {
    var tstScript = document.createElement ('script');
    tstScript.textContent = "TM_canaryIsAlive = true;";
    try {
        document.documentElement.appendChild (tstScript);
    }
    catch (zError) {
        console.log ("Local JS fails: " + zError);
        gbl_InlineJS_Works = false;
    }
    if (gbl_InlineJS_Works) {
        if ( ! unsafeWindow.TM_canaryIsAlive) {
            gbl_InlineJS_Works = false;
        }
    }
}

console.log (`Inline javascript ${gbl_InlineJS_Works ? "works!" : "is blocked."}`);
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
0

One way would be to access the page's headers. To do that you would have to issue a http request Accessing the web page's HTTP Headers in JavaScript

You could also look at some of these solutions How to detect Content Security Policy (CSP)

-- Update 1

This is basically untested. I ran it against facebook.com

function inlineScriptEnabled() {
  let req = new XMLHttpRequest();
  req.open('GET', document.location, false);
  req.send(null);
  let header = req.getResponseHeader('content-security-policy');
  if (!header)
    return true;
  let regex = /(^|\s)'unsafe-inline'(;|\s|$)/i; 
  return !!header.match(regex);
}
console.log(inlineScriptEnabled());

You should also search your document for meta tags as described here. https://developers.google.com/web/fundamentals/security/csp/#the_meta_tag The logic would be similar.

Community
  • 1
  • 1
Marc Rohloff
  • 1,332
  • 7
  • 8
  • Could you provide a working example of CSP detection via the page's HTTP headers? Using the solutions on the first page, I see no Content-Security-Policy headers (or anything of the sort, e.g. X-Content-Security-Policy). – Six Mar 12 '17 at 18:15
  • 2
    That appears to only tell me whether the site itself has CSP headers configured. It doesn't help when I use uBlock Origin (the Chrome extension) to block inline JavaScript with a filter like `*$inline-script,domain=stackoverflow.com`. – Six Mar 13 '17 at 18:07