Search code examples
javascriptfirefoxgreasemonkey

greasemonkey throws SecurityError for a simple script


I'm new to greasemonkey and trying to understand how greasemonkey is different from the embedded web console. A simple script which works perfectly on web console does not work on greasemonkey, and I have no idea why.

Environments

  • Firefox 74.0 on Arch Linux

  • Greasemonkey 4.9

Web Console

Here is the test script I use:

(function() {
    "use strict";

    const w = window.open('https://www.google.com/', 'w');

    console.log("Hello");

    w.onload = () => {
        console.log("World");
    };

})();

When I access https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0 (Google US top page), copy and paste the script into web console, and then execute it,

  1. A new window w loading https://www.google.com/ is opened.

  2. The string Hello is printed.

  3. The string World is printed.

Everything is as expected.

Greasemonkey

On greasemonkey, I use the script below. The header part is the only difference.

// ==UserScript==
// @name     test
// @namespace n
// @match https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0
// ==/UserScript==

(function() {
    "use strict";

    const w = window.open('https://www.google.com/', 'w');

    console.log("Hello");

    w.onload = () => {
        console.log("World");
    };

})();

When I access https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0 (Google US top page),

  1. A new window w loading https://www.google.com/ is opened.

  2. The string Hello is printed.

  3. SecurityError is thrown saying

    Script error in [Greasemonkey script n/test]:
    SecurityError: Permission denied to access property "onload" on cross-origin object test:42:19
        user-script:n/test:42

When I use unsafeWindow instead of window,

  1. A new window w loading https://www.google.com/ is opened.

  2. The string Hello is printed.

  3. And nothing else happens. (No error, no World)

Question

How should I modify the script so that is can be executed on greasemonkey?


Update

According to this comment, the script works on Tampermonkey or Violentmonkey under Chrome.

I haven't confirmed this but have confirmed that the script works on Tampermonkey 4.10.6105 or Violentmonkey 2.12.7 under Firefox.


Solution

  • Web Console is part of browser scope while a GreaseMonkey script is injected into a page content and its scope it limited to that page only.

    You can open a new tab/window from page content with GM but that window/tab will have its own page content scope which is separate from the first one. Therefore, you can not access properties belonging to another tab/window from a page content of different tab.

    This separation is for all content scripts and not only for GM. Otherwise, it would have created a great security risk if JS in one tab/page could access data on other tabs.

    Update:

    As pointed out by wOxxOm, the CSP and cross-origin policy prevents Cross-Origin Resource Sharing (CORS).

    In your example, in Firefox, the first issue is that Firefox will "Block pop-up windows" from the content script.

    Testing Firefox dedicated userScripts API on FireMonkey, after allowing popup, still causes an error:

    SecurityError: Permission denied to access property "onload" on cross-origin object

    In this case, I believe it is due to the sandboxing of userScripts for security.

    GM/TM/VM do not use the userScripts API and use other means to inject userSripts which results in different outcome.